RestTemplate的自定义配置及使用
前言
RestTemplate是最常用的Spring组件之一
封装了发送请求的多种方法,简单优雅的实现代码http交互
本文对RestTemplate的使用和配置进行示例,并参考相关博文(链接文中放出)和部分源码对配置进行解读
版本
本文示例工程版本
SpringBoot 2.0.8.RELEASE
工程结构
config
我们先进行最简单的示例,注入RestTemplate(好像是SpringBoot2后需要手动注入,之前不用,具体版本不作深究)
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
测试
@Test
public void test1() {
Object obj = restTemplate.getForObject(
"https://www.baidu.com"
, String.class);
System.out.println(obj);
}
一段优雅的http请求交互实现了
RestTemplate
一般地,上述RestTemplate就足够处理http请求了,但是实际业务我们往往需要个性化配置某些参数,比如请求超时时间?读取超时时间?底层http客户端?
我们简单康康源码
public class RestTemplate extends InterceptingHttpAccessor implements RestOperations
RestTemplate 继承 InterceptingHttpAccessor 并实现RestOperations接口
RestOperations
RestOperations接口见名知意,rest操作接口,其中定义了所有我们熟知的请求方法,例如
getForObject
<T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException;
postForObject
<T> T postForObject(URI url, @Nullable Object request, Class<T> responseType) throws RestClientException;
等,具体方法介绍可参考该博文
RestTemplate的使用和原理你都烂熟于胸了吗?
InterceptingHttpAccessor
public abstract class InterceptingHttpAccessor extends HttpAccessor
追溯该类到HttpAccessor
public abstract class HttpAccessor {
protected final Log logger = LogFactory.getLog(getClass());
private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
public void setRequestFactory(ClientHttpRequestFactory requestFactory) {
Assert.notNull(requestFactory, "ClientHttpRequestFactory must not be null");
this.requestFactory = requestFactory;
}
public ClientHttpRequestFactory getRequestFactory() {
return this.requestFactory;
}
protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {
ClientHttpRequest request = getRequestFactory().createRequest(url, method);
if (logger.isDebugEnabled()) {
logger.debug("Created " + method.name() + " request for \"" + url + "\"");
}
return request;
}
}
这个接口方法不多
我们发现
private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
默认的 RestTemplate 的 ClientHttpRequestFactory 为SimpleClientHttpRequestFactory
public void setRequestFactory(ClientHttpRequestFactory requestFactory)
该方法说明ClientHttpRequestFactory 允许我们自定义配置
而 ClientHttpRequestFactory 类中只有一个方法
ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException;
而源码中默认的createRequest实现为
protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {
ClientHttpRequest request = getRequestFactory().createRequest(url, method);
if (logger.isDebugEnabled()) {
logger.debug("Created " + method.name() + " request for \"" + url + "\"");
}
return request;
}
即SimpleClientHttpRequestFactory.createRequest,代码如下
@Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
HttpURLConnection connection = openConnection(uri.toURL(), this.proxy);
prepareConnection(connection, httpMethod.name());
if (this.bufferRequestBody) {
return new SimpleBufferingClientHttpRequest(connection, this.outputStreaming);
}
else {
return new SimpleStreamingClientHttpRequest(connection, this.chunkSize, this.outputStreaming);
}
}
可以发现Http客户端为JDK内置的HttpURLConnection
而且在SimpleClientHttpRequestFactory类中可以看到如下方法
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
}
public void setReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
}
看到这不难猜测,我们刚才提到的那些配置比如
连接超时时间,读取超时时间,Http客户端等都可以通过set不同的ClientHttpRequestFactory 来自定义的配置
ClientHttpRequestFactory
然后我们再来简单的看一下ClientHttpRequestFactory 都有哪些实现类
根据各种类名我们可以简单的猜测
单元测试常用的MockMvcClientHttpRequestFactory
OkHttp客户端的OkHttp3ClientHttpRequestFactory,HttpClient客户端的HttpComponentsClientHttpRequestFactory
(不同的客户端需要引入单独的依赖)
等等
更详细实现类的介绍点这里
尝试
现在我们尝试用当前的理解去配置
引入HttpClient依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.10</version>
</dependency>
修改RestTemplate配置,此处先不用builder模式
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory
= new HttpComponentsClientHttpRequestFactory();
httpComponentsClientHttpRequestFactory.setConnectTimeout(1000);
httpComponentsClientHttpRequestFactory.setReadTimeout(1000);
restTemplate.setRequestFactory(httpComponentsClientHttpRequestFactory);
return restTemplate;
}
测试
@Test
public void test2() {
Object obj = restTemplate.getForObject(
"http://localhost:10601/test?name=dd"
, String.class);
System.out.println(obj);
}
对应controller代码,我们加入两秒的读取延时
@GetMapping(value = "/test")
public String test(@RequestParam(name = "name") String name) throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
return "hello " + name;
}
结果读取超时,说明配置生效~
继续
再回到我们最初的配置
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
此处明显是使用了建造者模式,因此我们可以更优雅地去配置
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.requestFactory(HttpComponentsClientHttpRequestFactory.class)
.setConnectTimeout(1000)
.setReadTimeout(1000)
.build();
}
总结
至此,我们对RestTemplate及其配置进行了简单介绍,对于各种不同的业务需要,我们可以进一步去了解对应的配置类,自定义的配置
源码地址
https://github.com/dangzhicairang/my-cloud.git
配置中心地址
https://github.com/dangzhicairang/my-config.git