源码解析-Spring RestTemplate

471 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情

RestTemplate是Spring提供的一种更优雅的调用RESTful服务的方式,它简化了与http服务的通信方式,统一了RESTful的标准,封装了HTTP链接,还可以自定义RestTemplate所需的模式。

类依赖关系图

image.png

  • HttpAccessor是一个抽象类,它抽象的是一个http访问器的概念。
  • RestOperations是一个接口,抽象的是restful风格的操作方法。
  • RestTemplate则是聚合了两者,既有http访问器的基础能力,又在这个基础之上构建了restful风格。

组成部分

ClientHttpRequestFactory:ClientHttpRequest工厂类,通过ClientHttpRequestInterceptor自定义 ClientHttpRequest:代表客户端HTTP请求的抽象 ResponseErrorHandler:异常处理 ClientHttpRequestInterceptor:请求拦截器 HttpMessageConverter:对象转换器

contentType与messageConverter之间的关系

类名支持的JavaType支持的MediaType
ByteArrayHttpMessageConverterbyte[]application/octet-stream, /
StringHttpMessageConverterStringtext/plain, /
ResourceHttpMessageConverterResource/
SourceHttpMessageConverterSourceapplication/xml, text/xml, application/*+xml
AllEncompassingFormHttpMessageConverterMap<K, List<?>>application/x-www-form-urlencoded, multipart/form-data
MappingJackson2HttpMessageConverterObjectapplication/json, application/*+json
Jaxb2RootElementHttpMessageConverterObjectapplication/xml, text/xml, application/*+xml
JavaSerializationConverterSerializablex-java-serialization;charset=UTF-8
FastJsonHttpMessageConverterObject/

核心逻辑

  1. new RestTemplate():添加HttpMessageConverter;初始化UriTemplateHandler
  2. restTemplate.getForObject:调用RestTemplate.doExecute方法
  3. createRequest(url, method):工厂类创建HTTP请求对象
  4. request.execute():执行请求,调用InterceptingClientHttpRequest.executeInternal
  5. requestExecution.execute:执行拦截器处理,最后执行HTTP请求
  6. delegate.execute:执行请求,获取响应
  7. handleResponse(url, method, response):处理ClientHttpResponse响应对象

源码分析

org.springframework.web.client.RestTemplate.java

protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback,
		@Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {
	ClientHttpResponse response = null;
	try {
	  // 创建HTTP请求对象,调用InterceptingClientHttpRequest.executeInternal
		ClientHttpRequest request = createRequest(url, method);
		if (requestCallback != null) {
	    // 设置header
			requestCallback.doWithRequest(request);
		}
		// 执行请求,获取响应
		response = request.execute();
		// 处理响应
		handleResponse(url, method, response);
		// 响应数据提取
		return (responseExtractor != null ? responseExtractor.extractData(response) : null);
	}
	catch (IOException ex) {
		throw new ResourceAccessException("I/O error on " + method.name() + " request for \"" + resource + "\": " + ex.getMessage(), ex);
	} finally {
		response.close();
	}
}

org.springframework.http.client.InterceptingClientHttpRequest.java

@Override
protected final ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
	InterceptingRequestExecution requestExecution = new InterceptingRequestExecution();
	return requestExecution.execute(this, bufferedOutput);
}

private class InterceptingRequestExecution implements ClientHttpRequestExecution {
	@Override
	public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException {
	  // 执行拦截器
		if (this.iterator.hasNext()) {
			ClientHttpRequestInterceptor nextInterceptor = this.iterator.next();
			return nextInterceptor.intercept(request, body, this);
		}
		else {
			HttpMethod method = request.getMethod();
			// 工厂类创建HTTP请求对象
			ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), method);
			// 执行请求
			return delegate.execute();
		}
	}
}

使用

HTTP方法说明

方法描述
delete()在特定的URL上对资源执行HTTP DELETE操作
getForEntity()发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象
getForObject()发送一个HTTP GET请求,返回的请求体将映射为一个对象
postForEntity()POST 数据到一个URL,返回包含一个对象的ResponseEntity
postForObject()POST 数据到一个URL,返回根据响应体匹配形成的对象
put()PUT 资源到特定的URL
......
  1. 配置
@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory simleClientHttpRequestFactory) {
        RestTemplate restTemplate = new RestTemplate();
        reqFactory.setConnectTimeout(restTemplateConnectionTimeout);
        reqFactory.setReadTimeout(restTemplateReadTimeout);
        //配置自定义的message转换器
        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        messageConverters.add(new CustomMappingJackson2HttpMessageConverter());
        restTemplate.setMessageConverters(messageConverters);
        //配置自定义的interceptor拦截器
        List<ClientHttpRequestInterceptor> interceptors=new ArrayList<ClientHttpRequestInterceptor>();
        interceptors.add(new HeadClientHttpRequestInterceptor());
        interceptors.add(new TrackLogClientHttpRequestInterceptor());
        restTemplate.setInterceptors(interceptors);
        //配置自定义的异常处理
        restTemplate.setErrorHandler(new CustomResponseErrorHandler());
        restTemplate.setRequestFactory(simleClientHttpRequestFactory);
        return restTemplate;
    }
}
  1. 使用
@RestController
public class Demo1Controller {
    @Autowired
    private RestTemplate restTemplate;
    @GetMapping(value = "/user/list")
    public List<User> userList() {
        return restTemplate.getForObject("http://unififi-demo2-service/user/list", List.class);
    }
}