引言
SpringCloud的微服务均是以Http接口的形式来暴露自身服务的,因此在调用远程服务的时候必须使用HTTP客户端,可选的方案有JDK原生的URL Connection、Apache的Http Client、Netty的异步Http Client,Spring的RestTemplate和Fegin。
今天主要介绍一下Spring的RestTemplate。
源码跟读
通过源码可以看到RestTemplate进行请求的很多方法最终调用的均是doExecute方法。
可以看出,主要分为创建请求Request,执行请求Request,处理返回结果response3个步骤。
创建请求
跟进createRequest()方法,发现该方法是由HttpAccessor负责实现的。
其基本思路是传入请求地址url和请求方法method,然后由ClientHttpRequestFactory工厂负责Request的创建,ClientHttpRequestFactory为一个接口,其实现类主要有:
HttpAccessor提供了get/set方法,方便传入不同的ClientHttpRequestFactory实现类,如果需要自定义ClientHttpRequestFactory工厂,直接implements ClientHttpRequestFactory复写方法,然后注入HttpAccessor即可。
HttpAccessor默认使用的是SimpleClientHttpRequestFactory工厂实现类。
继续跟进SimpleClientHttpRequestFactory工厂实现类。
它提供了两种请求创建方法,分别支持同步和异步请求:
- createRequest(URI uri, HttpMethod httpMethod)
- createAsyncRequest(URI uri, HttpMethod httpMethod)
上述两种方法均包括打开连接、准备连接、创建连接3个步骤。
先看openConnection方法,它的实现比较简单,有代理Proxy存在,则传入Proxy打开连接,否则则直接通过URL打来连接。
prepareConnection方法主要根据传入的参数,进行连接前的一些配置工作,比如设置连接超时、读取超时、根据不同请求method设置相应配置参数等。
最后创建连接的时候,根据bufferRequestBody是否为True,创建2种不同的连接,分别为批处理连接和流处理连接。
return (ClientHttpRequest)(this.bufferRequestBody ? new SimpleBufferingClientHttpRequest(connection, this.outputStreaming) : new SimpleStreamingClientHttpRequest(connection, this.chunkSize, this.outputStreaming));
执行请求
切回到RestTemplate类的doExecute方法,可以看到建立http连接,拿到ClientHttpRequest后,执行请求的方法为execute()。
ClientHttpRequest为接口,仅有一个execute()方法,看一下ClientHttpRequest的实现类:
其中用的比较多的是AbstractClientHttpRequest抽象类,SimpleStreamingClientHttpRequest和SimpleBufferingClientHttpRequest分别继承了AbstractClientHttpRequest,复写某些方法以支持流/批处理请求。
跟进AbstractClientHttpRequest抽象类的execute()方法,
execute()内部调用的是executeInternal(),由子类来具体实现,可以看一下SimpleBufferingClientHttpRequest的方法实现,其他子类实现方式大同小异。
可以看到,主要是做了一些添加请求头、返回设置等的操作,最后得到请求的返回类SimpleClientHttpResponse。
至此,我们就拿到请求的返回了,下一步就是处理返回结果了。
处理返回结果
返回结果处理主要分为两步:
- handleResponse(url, method, response)
- responseExtractor.extractData(response)
其中,handleResponse(url, method, response)主要负责对请求的异常进行处理。
可以看到,handleResponse()方法首先获取请求错误的处理器errorHandler,然后把response交给它进行后续的处理。
而responseExtractor.extractData(response)主要负责返回数据的解析。
responseExtractor为接口,其实现类为:
其中ResponseEntityResponseExtractor和HeadersExtractor为RestTemplate的内部类,主要处理返回的headers和entity,我们重点关注返回消息的转化处理类HttpMessageConverterExtractor。
可以看到,extractData先将response交给responseWrapper,如果responseWrapper有消息体且非空,则进行返回消息的读取操作。
消息的读取需要借助HttpMessageConverter接口,HttpMessageConverter具有多种实现类,以完成不同格式消息的读取,相当于消息解码器或转换头。
可以看到,在构建HttpMessageConverterExtractor实例的时候,需要传入HttpMessageConverter的接口集合messageConverters,用于对不同返回格式消息的读取。
首先,得到messageConverters的迭代器,然后遍历迭代器,依次执行不同HttpMessageConverter读取操作,最终完成返回消息体的读取操作。
迭代过程中,如果当前MessageConverter属于GenericHttpMessageConverter的接口实现,则执行:
return genericMessageConverter.read(this.responseType, (Class)null, responseWrapper);
否则:
return messageConverter.read(this.responseClass, responseWrapper);
总结
-
RestTemplate是Spring提供的用于访问Rest服务的客户端;
-
RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率;
-
调用RestTemplate的默认构造函数,RestTemplate对象在底层通过使用java.net包下的实现创建HTTP请求;
-
可以通过使用ClientHttpRequestFactory指定不同的HTTP请求方式;
-
在设计模式上,主要通过工厂模式来完成各类Http客户端的创建。