基础
推荐使用RestTemplateBuilder构建RestTemplate
我们看下RestTemplate的基础成员变量
requestFactory: ClientHttpRequestFactorydefaultUriVariables: Map<String, ?>uriTemplateHandler: UriTemplateHandlerinterceptors: 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<?>>(); |