关注我,可以获取最新知识、经典面试题以及微服务技术分享
在微服务中,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技术博客】,原创技术文章第一时间推出
本文转载自: 掘金