基础
推荐使用RestTemplateBuilder
构建RestTemplate
我们看下RestTemplate
的基础成员变量
requestFactory: ClientHttpRequestFactory
defaultUriVariables: Map<String, ?>
uriTemplateHandler: UriTemplateHandler
interceptors: List<ClientHttpRequestInterceptor>
messageConverters: List<HttpMessageConverter<?>>
errorHandler: ResponseErrorHandler
下面我们主要针对这些属性做一些分析
requestFactory
指定使用的HTTP
请求方式, 设置http
请求工厂类,处理超时,线程,异常处理等情况。
1 | RestTemplate restTemplate() { |
defaultUriVariables
当被赋值时就不能使用自定义uriTemplateHandler
。这是就使用默认的uriTemplateHandler
即DefaultUriBuilderFactory
。 假设现在defaultUriVariables
包含default=demo
。
例如:
1 | String url = "http://localhost:8080/{default}/{replace}" |
在实际请求时: {default}
会被替换为demo
{replace}
会被替换为someuri
替换后的值中包含/
会无法正常解析。
uriTemplateHandler
默认的 uriTemplateHandler 会将 uriVariables 中的 value 进行转译,因此无法'/'会被解析为 ascii 符号。根据需要,生成满足自己需要的 URI。
1 | public interface UriTemplateHandler { |
返回的 URI 经过自定义处理器会将{xxx}
,替换为uriVariables
中对应的值,这个可以正常解析/
1 | RestTemplate rest = restTemplate(); |
interceptors
类似AOP
切面,在HTTP
请求前后进行拦截,比如统一加`headers
1 | public interface ClientHttpRequestInterceptor { |
messageConverters
与SpringMVC
的messageConverters
原理是一样的。HTTP
交易时数据传递是通过二进制byte
传递的。而我们使用RestTemplate
时,一般请求返回都使用javaBean
,那就需要messageConverters
来统一处理。
我们看下RestTemplate
的静态方法
1 | private static boolean romePresent; |
再看下RestTemplate
构造器,当classpath
中有对应的class
时,可以看到RestTemplate
会自动加载
1 | public RestTemplate() { |
errorHandler
仅在HTTP
成功返回后才会被执行,决定当前HTTP
请求是否成功。hasError
返回true
时才会调用handleError
方法。
1 | public interface ResponseErrorHandler { |
rootUri
通过RestTemplateBuilder
设置rootUri
,进行HTTP
请求时,若非http
开头,则会自动加上rootUri
1 | RestTemplate rest = new RestTemplateBuilder().rootUri("http://localhost:8080").build(); |
POST 请求参数
上传文件的请求模拟
1 | RestTemplate restTemplate = new RestTemplate(); |
上传文件的错误
错误信息
The request was rejected because no multipart boundary was found
通过查找该报错信息打印处可以定位
1 | FileItemIteratorImpl(RequestContext ctx) |
通过查看getBoundary
1 | protected byte[] getBoundary(String contentType) { |
根据上一节的说明,我们知道上送文件是使用MultiValueMap
来上送的,那么我们只要知道MultiValueMap
请求的Content-Type
是什么即可。
根据前面章节messageConverters
的加载介绍,我们知道RestTemplate
会选择一个合适的处理器来处理, 其中AllEncompassingFormHttpMessageConverter
的父类FormHttpMessageConverter
1 | public void doWithRequest(ClientHttpRequest httpRequest) throws IOException { |
查看具体FormHttpMessageConverter
的write
方法
1 | public void write(MultiValueMap<String, ?> map, @Nullable MediaType contentType, HttpOutputMessage outputMessage) |
1 | private void writeMultipart(final MultiValueMap<String, Object> parts, HttpOutputMessage outputMessage) |
所以我们定位一下具体发生错误的情况下使用的是何种messageConverter
即可
messageConverter
有关问题
当请求的api
返回的content-type
不是标准的application/json
时,默认的messageConverter
不支持处理
1 | List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>(); |