【源码笔记】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();

默认的 RestTemplateClientHttpRequestFactorySimpleClientHttpRequestFactory

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

猜你喜欢

转载自blog.csdn.net/weixin_42189048/article/details/106875818
今日推荐