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 <em>only</em> 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;