关注我,可以获取最新知识、经典面试题以及微服务技术分享
在微服务中,rest
服务互相调用是很普遍的,我们该如何优雅地调用,其实在Spring框架使用RestTemplate
类可以优雅地进行rest
服务互相调用,它简化了与http
服务的通信方式,统一了RESTful
的标准,封装了http
链接,操作使用简便,还可以自定义RestTemplate所需的模式。其中:
RestTemplate
默认使用HttpMessageConverter
实例将HTTP
消息转换成POJO
或者从POJO
转换成HTTP
消息。默认情况下会注册主mime
类型的转换器,但也可以通过setMessageConverters
注册自定义转换器。RestTemplate
使用了默认的DefaultResponseErrorHandler
,对40XBad Request
或50Xinternal
异常error
等错误信息捕捉。RestTemplate
还可以使用拦截器interceptor
,进行对请求链接跟踪,以及统一head的设置。
其中,RestTemplate
还定义了很多的REST
资源交互的方法,其中的大多数都对应于HTTP
的方法,如下:
方法 | 解析 |
---|---|
delete() | 在特定的URL上对资源执行HTTP DELETE操作 |
exchange() | 在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity |
execute() | 在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象 |
getForEntity() | 发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象 |
getForObject() | 发送一个HTTP GET请求,返回的请求体将映射为一个对象 |
postForEntity() | POST 数据到一个URL,返回包含一个对象的ResponseEntity |
postForObject() | POST 数据到一个URL,返回根据响应体匹配形成的对象 |
headForHeaders() | 发送HTTP HEAD请求,返回包含特定资源URL的HTTP头 |
optionsForAllow() | 发送HTTP OPTIONS请求,返回对特定URL的Allow头信息 |
postForLocation() | POST 数据到一个URL,返回新创建资源的URL |
put() | PUT 资源到特定的URL |
- RestTemplate源码
1.1 默认调用链路
restTemplate
进行API调用时,默认调用链:
1 | 复制代码###########1.使用createRequest创建请求######## |
1.2 restTemplate->doExecute()
在默认调用链中,restTemplate
进行API调用都会调用 doExecute
方法,此方法主要可以进行如下步骤:
1)使用createRequest
创建请求,获取响应
2)判断响应是否异常,处理异常
3)将响应消息体封装为java对象
1 | 复制代码@Nullable |
1.3 InterceptingHttpAccessor->getRequestFactory()
在默认调用链中,InterceptingHttpAccessor的getRequestFactory()
方法中,如果没有设置interceptor
拦截器,就返回默认的SimpleClientHttpRequestFactory
,反之,返回InterceptingClientHttpRequestFactory
的requestFactory
,可以通过resttemplate.setInterceptors
设置自定义拦截器interceptor
。
1 | 复制代码//Return the request factory that this accessor uses for obtaining client request handles. |
然后再调用SimpleClientHttpRequestFactory的createRequest
创建连接:
1 | 复制代码@Override |
1.4 resttemplate->handleResponse()
在默认调用链中,resttemplate的handleResponse
,响应处理,包括异常处理,而且异常处理可以通过调用setErrorHandler
方法设置自定义的ErrorHandler
,实现对请求响应异常的判别和处理。自定义的ErrorHandler
需实现ResponseErrorHandler
接口,同时Spring boot
也提供了默认实现DefaultResponseErrorHandler
,因此也可以通过继承该类来实现自己的ErrorHandler
。
DefaultResponseErrorHandler
默认对40X Bad Request
或50X internal
异常error
等错误信息捕捉。如果想捕捉服务本身抛出的异常信息,需要通过自行实现RestTemplate
的ErrorHandler
。
1 | 复制代码ResponseErrorHandler errorHandler = getErrorHandler(); |
1.5 HttpMessageConverterExtractor->extractData()
在默认调用链中, HttpMessageConverterExtractor
的extractData
中进行响应消息体封装为java
对象,就需要使用message
转换器,可以通过追加的方式增加自定义的messageConverter
:先获取现有的messageConverter
,再将自定义的messageConverter
添加进去。
根据restTemplate
的setMessageConverters
的源码可得,使用追加的方式可防止原有的messageConverter
丢失,源码:
1 | 复制代码public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) { |
HttpMessageConverterExtractor的extractData
源码:
1 | 复制代码MessageBodyClientHttpResponseWrapper responseWrapper = new MessageBodyClientHttpResponseWrapper(response); |
1.6 contentType与messageConverter之间的关系
在HttpMessageConverterExtractor
的extractData
方法中看出,会根据contentType
与responseClass
选择messageConverter
是否可读、消息转换。关系如下:
类名 | 支持的JavaType | 支持的MediaType |
---|---|---|
ByteArrayHttpMessageConverter | byte[] | application/octet-stream, */* |
StringHttpMessageConverter | String | text/plain, */* |
ResourceHttpMessageConverter | Resource | */* |
SourceHttpMessageConverter | Source | application/xml, text/xml, application/*+xml |
AllEncompassingFormHttpMessageConverter | Map<K, List<?>> | application/x-www-form-urlencoded, multipart/form-data |
MappingJackson2HttpMessageConverter | Object | application/json, application/*+json |
Jaxb2RootElementHttpMessageConverter | Object | application/xml, text/xml, application/*+xml |
JavaSerializationConverter | Serializable | x-java-serialization;charset=UTF-8 |
FastJsonHttpMessageConverter | Object | */* |
- springboot集成RestTemplate
根据上述源码的分析学习,可以轻松,简单地在项目进行对RestTemplate进行优雅地使用,比如增加自定义的异常处理、MessageConverter
以及拦截器interceptor
。本文使用示例demo
,详情请查看接下来的内容。
2.1. 导入依赖:(RestTemplate集成在Web Start中)
1 | 复制代码<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web --> |
2.2. RestTemplat配置:
- 使用
ClientHttpRequestFactory
属性配置RestTemplat参数,比如ConnectTimeout
,ReadTimeout
; - 增加自定义的
interceptor
拦截器和异常处理; - 追加
message
转换器; - 配置自定义的异常处理.
1 | 复制代码 @Configuration |
2.3. 组件(自定义异常处理、interceptor拦截器、message转化器)
自定义interceptor
拦截器,实现ClientHttpRequestInterceptor
接口
- 自定义
TrackLogClientHttpRequestInterceptor
,记录resttemplate
的request
和response
信息,可进行追踪分析; - 自定义
HeadClientHttpRequestInterceptor
,设置请求头的参数。API发送各种请求,很多请求都需要用到相似或者相同的Http Header。如果在每次请求之前都把Header
填入HttpEntity/RequestEntity
,这样的代码会显得十分冗余,可以在拦截器统一设置。
TrackLogClientHttpRequestInterceptor:
1 | 复制代码/** |
HeadClientHttpRequestInterceptor:
1 | 复制代码@Slf4j |
自定义异常处理,可继承DefaultResponseErrorHandler
或者实现ResponseErrorHandler
接口:
- 实现自定义
ErrorHandler
的思路是根据响应消息体进行相应的异常处理策略,对于其他异常情况由父类DefaultResponseErrorHandler
来进行处理。 - 自定义
CustomResponseErrorHandler
进行30x异常处理
CustomResponseErrorHandler:
1 | 复制代码/** |
自定义message转化器
1 | 复制代码/** |
各位看官还可以吗?喜欢的话,动动手指点个💗,点个关注呗!!谢谢支持!
欢迎关注公众号【Ccww技术博客】,原创技术文章第一时间推出
本文转载自: 掘金