restTemplate禁用url编码

restTemplate禁用url编码

在restTemplate调用方法的时候默认对url做了编码处理

  • 如果路径里面带了参数,url?param={"name":"张三","age":22}
  • 这时这处理url的时候就要先对json数据进行编码处理
url?param=%7B%22name%22%3A%22%E5%BC%A0%E4%B8%89%22%EF%BC%8C%22age%22%3A22%7D
  • 这时使用restTemplate调用接口,会对url再次编码成
url%3Fparam%3D%257B%2522name%2522%253A%2522%25E5%25BC%25A0%25E4%25B8%2589%2522%25EF%25BC%258C%2522age%2522%253A22%257D
  • 接口放接收到路径解码后
url?param=%7B%22name%22%3A%22%E5%BC%A0%E4%B8%89%22%EF%BC%8C%22age%22%3A22%7D

并不是url?param={"name":"张三","age":22}

  • 我们想要的结果并不想restTemplate调用的时候二次编码,而是使用我们的url

查询看restTemplate源码

  • postForObject方法
	@Override
	@Nullable
	public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType,
			Object... uriVariables) throws RestClientException {

		RequestCallback requestCallback = httpEntityCallback(request, responseType);
		HttpMessageConverterExtractor<T> responseExtractor =
				new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
		return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
	}
  • 跟进去到execute方法,可以看到对url做了处理
	@Override
	@Nullable
	public <T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback,
			@Nullable ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException {
        // 对url做了处理
		URI expanded = getUriTemplateHandler().expand(url, uriVariables);
		return doExecute(expanded, method, requestCallback, responseExtractor);
	}
  • restTemplate默认的url模版,restTemplate的无参构造函数
	public RestTemplate() {
		this.messageConverters.add(new ByteArrayHttpMessageConverter());
		this.messageConverters.add(new StringHttpMessageConverter());
		this.messageConverters.add(new ResourceHttpMessageConverter(false));
		try {
			this.messageConverters.add(new SourceHttpMessageConverter<>());
		}
		catch (Error err) {
			// Ignore when no TransformerFactory implementation is available
		}
		this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());

		if (romePresent) {
			this.messageConverters.add(new AtomFeedHttpMessageConverter());
			this.messageConverters.add(new RssChannelHttpMessageConverter());
		}

		if (jackson2XmlPresent) {
			this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
		}
		else if (jaxb2Present) {
			this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
		}

		if (jackson2Present) {
			this.messageConverters.add(new MappingJackson2HttpMessageConverter());
		}
		else if (gsonPresent) {
			this.messageConverters.add(new GsonHttpMessageConverter());
		}
		else if (jsonbPresent) {
			this.messageConverters.add(new JsonbHttpMessageConverter());
		}

		if (jackson2SmilePresent) {
			this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
		}
		if (jackson2CborPresent) {
			this.messageConverters.add(new MappingJackson2CborHttpMessageConverter());
		}
        // 默认的url处理器
		this.uriTemplateHandler = initUriTemplateHandler();
	}
  • 默认模版
	private static DefaultUriBuilderFactory initUriTemplateHandler() {
		DefaultUriBuilderFactory uriFactory = new DefaultUriBuilderFactory();
		uriFactory.setEncodingMode(EncodingMode.URI_COMPONENT);  // for backwards compatibility..
		return uriFactory;
	}
  • URI_COMPONENT 枚举值的解释
		/**
		 * Expand URI variables first, and then encode the resulting URI
		 * component values, replacing only non-ASCII and illegal
		 * (within a given URI component type) characters, but not characters
		 * with reserved meaning.
		 * @see UriComponents#encode()
		 */
		URI_COMPONENT

禁用restTemplate对url编码

    @Bean
    public RestTemplate restTemplateNoEncode(RestTemplateBuilder builder) {
        RestTemplate build = builder.build();
        DefaultUriBuilderFactory defaultUriBuilderFactory = new DefaultUriBuilderFactory();
        // 不对url进行编码
        defaultUriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
        build.setUriTemplateHandler(defaultUriBuilderFactory);
        return build;
    }

在代码中定义多个restTemplate

@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        RestTemplate build = builder.build();
        List<HttpMessageConverter<?>> messageConverters = build.getMessageConverters();
        messageConverters.add(new CustomJacksonHttpMessageConverter());
        return build;
    }

    @Bean
    public RestTemplate restTemplateNoEncode(RestTemplateBuilder builder) {
        RestTemplate build = builder.build();
        DefaultUriBuilderFactory defaultUriBuilderFactory = new DefaultUriBuilderFactory();
        defaultUriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
        List<HttpMessageConverter<?>> messageConverters = build.getMessageConverters();
        messageConverters.add(new CustomJacksonHttpMessageConverter());
        build.setUriTemplateHandler(defaultUriBuilderFactory);
        return build;
    }
}

  • 使用的时候使用@Qualifier指定名称就可以
    @Autowired
    @Qualifier("restTemplateNoEncode")
    private RestTemplate restTemplate;

你可能感兴趣的:(spring,spring,boot)