网站首页 > 技术文章 正文
一、RestOperations
定义符合rest规范的接口,包含 get post head delete等一系列接口方法很多,最终调用的都是 execute方法。
二、HttpAccessor
抽象父类http访问器,通过 ClientHttpRequestFactory 创建 ClientHttpRequest
public abstract class HttpAccessor {
protected final Log logger = LogFactory.getLog(getClass());
private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
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;
}
}
三、InterceptingHttpAccessor
具有拦截器功能的HttpAccessor ,相当于是一种装饰者设计模式
public abstract class InterceptingHttpAccessor extends HttpAccessor {
private final List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
@Nullable
private volatile ClientHttpRequestFactory interceptingRequestFactory;
// 维护一个拦截器列表,并且将拦截器排序
public void setInterceptors(List<ClientHttpRequestInterceptor> interceptors) {
// Take getInterceptors() List as-is when passed in here
if (this.interceptors != interceptors) {
this.interceptors.clear();
this.interceptors.addAll(interceptors);
AnnotationAwareOrderComparator.sort(this.interceptors);
}
}
// 如果有拦截器,则使用 InterceptingClientHttpRequestFactory,否则 使用普通的 ClientHttpRequestFactory
@Override
public ClientHttpRequestFactory getRequestFactory() {
List<ClientHttpRequestInterceptor> interceptors = getInterceptors();
if (!CollectionUtils.isEmpty(interceptors)) {
ClientHttpRequestFactory factory = this.interceptingRequestFactory;
if (factory == null) {
factory = new InterceptingClientHttpRequestFactory(super.getRequestFactory(), interceptors);
this.interceptingRequestFactory = factory;
}
return factory;
}
else {
return super.getRequestFactory();
}
}
}
四、RestTemplate
RestTemplate是一个在 jdk的httpUrlConnection,apache HttpComponents,okhttp3等其他的工具类库之上封装的一个简单且有模板方法api的同步执行http请求的客户端。
RestTemplate为常见场景提供模板,并且为少见场景提供了exchange和execute接口。
首先从继承关系可以看出 RestTemplate 实现 RestOperations的一系列get post 等接口, 继承 InterceptingHttpAccessor的拦截器功能。
public class RestTemplate extends InterceptingHttpAccessor implements RestOperations {
private final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
private ResponseErrorHandler errorHandler = new DefaultResponseErrorHandler();
private UriTemplateHandler uriTemplateHandler = new DefaultUriBuilderFactory();
private final ResponseExtractor<HttpHeaders> headersExtractor = new HeadersExtractor();
}
4.1、成员变量
1、messageConverters
HttpMessageConverter消息转换器集合
1、在发起http请求之前,将请求体参数对象进行转换序列化,写进ClientHttpRequest对象
2、调用http请求之后,从ClientHttpResponse中拿到响应体,转换得到对应的Class对象
2、errorHandler
用于解析Response响应如果发生错误(例如statusCode是404 500等一系列错误码)时,执行errorHandler逻辑
3、uriTemplateHandler
uri模板处理器,例如url会写成http://host:port/get/{name}这种,然后传入参数name=11,通过uriTemplateHandler会解析转换成完整的路径 http://host:port/get/11
4、headersExtractor
针对 head或者option请求时,用于从ClientHttpResponse从提取header信息
4.2、成员方法
只分析常用的get和post方法
ForObject和ForEntity实现基本一样
ForObject返回业务上的responseType
ForEntity返回的是ResponseEntity,需要进一步使用ResponseEntity.getBody()才能得到 responseType
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType); // 创建一个AcceptHeaderRequestCallback
HttpMessageConverterExtractor<T> responseExtractor =
new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);// 创建响应消息提取器(通过消息转换器集合)
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
}
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)
throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return nonNull(execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
}
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType,
Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request, responseType); //创建一个HttpEntityRequestCallback
HttpMessageConverterExtractor<T> responseExtractor =
new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}
public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request,
Class<T> responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return nonNull(execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables));
}
3、doExecute (最终调用的方法)
protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback,
@Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {
Assert.notNull(url, "URI is required");
Assert.notNull(method, "HttpMethod is required");
ClientHttpResponse response = null;
try {
//1、真正的ClientHttpRequestFactory创建真正的ClientHttpRequest
ClientHttpRequest request = createRequest(url, method);
if (requestCallback != null) {
// 2、request回调处理
requestCallback.doWithRequest(request);
}
//3、真正的request发起http请求调用
response = request.execute();
//4、处理ClientHttpResponse,主要是errorHandler
handleResponse(url, method, response);
//5、从response中提取结果(转换成ResponseType)
return (responseExtractor != null ? responseExtractor.extractData(response) : null);
}
catch (IOException ex) {
String resource = url.toString();
String query = url.getRawQuery();
resource = (query != null ? resource.substring(0, resource.indexOf('?')) : resource);
throw new ResourceAccessException("I/O error on " + method.name() +
" request for \"" + resource + "\": " + ex.getMessage(), ex);
}
finally {
if (response != null) {
response.close();
}
}
}
4.3、RequestCallback
回调接口,可以操纵 请求头和请求体
4.4、AcceptHeaderRequestCallback
设置客户端希望接受的数据格式
4.5、HttpEntityRequestCallback
设置客户端此次发送的数据的数据格式
4.6、ResponseEntityResponseExtractor
将ClientHttpResponse转换成 ResponseEntity
private class ResponseEntityResponseExtractor<T> implements ResponseExtractor<ResponseEntity<T>> {
// 相当于采用适配模式封装了HttpMessageConverterExtractor
@Nullable
private final HttpMessageConverterExtractor<T> delegate;
public ResponseEntityResponseExtractor(@Nullable Type responseType) {
if (responseType != null && Void.class != responseType) {
this.delegate = new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
}
else {
this.delegate = null;
}
}
// 将HttpMessageConverterExtractor转换后的responseType对象 包装成了ResponseEntity
@Override
public ResponseEntity<T> extractData(ClientHttpResponse response) throws IOException {
if (this.delegate != null) {
T body = this.delegate.extractData(response);
return ResponseEntity.status(response.getRawStatusCode()).headers(response.getHeaders()).body(body);
}
else {
return ResponseEntity.status(response.getRawStatusCode()).headers(response.getHeaders()).build();
}
}
}
4.7、HttpMessageConverterExtractor
将ClientHttpResponse返回的body响应体 从字节流 通过 HttpMessageConverter转换器集合 转换成 对应的 ResponseType 对象
五、总结
RestTemplate没有提供新的http请求调用方式,还是基于spring-web5.0里的http客户端模型之上做了适配,提供多种模板进行访问,对请求参数和返回参数进行处理,并没有特别新的东西。
猜你喜欢
- 2024-09-08 精讲RestTemplate第7篇-自定义请求失败异常处理
- 2024-09-08 java实现调用http请求的几种常见方式
- 2024-09-08 深度原理学习——白话TCP与HTTP的keep–alive机制
- 2024-09-08 有了WebClient还在用RestTemplate?
- 2024-09-08 Spring Boot外部接口调用:使用RestTemplate与WebClient操控HTTP
- 2024-09-08 Java服务优雅上下线(java项目如何上线)
- 2024-09-08 Spring 框架里的 HTTP 调用,RestTemplate 还是 WebClient
- 2024-09-08 微服务中如何使用RestTemplate优雅调用API(详细分析)
- 2024-09-08 真不是吹,Spring 里这款牛逼的网络工具库你可能没用过
- 2024-09-08 Java工具类封装微服务间HTTP通信(java md5工具类)
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)