网站首页 > 技术文章 正文
RestTemplate的概述
spring 架构中,RestTemplate是客户端http请求的核心类,它使和服务端的请求更加简单,同时强化了RestFul的原理,它会处理http请求的连接,使应用代码只需提供url和参数,解析结果就可以了。
RestTemplate默认是依赖于标准sdk 工具去建立连接,你可以通过setRequestFactory方法用其它的http库来替换,比如apache httpComponents,Netty 和OkHttp
RestTemplate的类图
- HttpAccessor 类
RestTemplate的基类,是一个抽象类,提供了一些公共的属性,如 ClientHttpRequestFactory,ClientHttpRequestFactory 是clientHttpRequest的工厂类,通过 createRequest 来创建http请求的方法 - InterceptingHttpAccessor 类
这个是 HttpAccessor的一个抽象子类,多增加了 请求拦截器相关的属性,ClientHttpRequestInterceptor,而这个ClientHttpRequestInterceptor是 spring cloud中各种服务治理的关键,如客户端负载均衡,链路跟踪等
- RestTemplate的doExecute 方法
该方法是RestTemplate的核心方法
它主要有四个参数
- url 请求的http 地址
- method http请求的method
- requestCallback 是一个接口Request Callback
- responseExtractor 也是一个接口 ResponseExtractor
我们来设想下,如果我们自己设计一个封装http请求的组件,一定也会遵守开闭原则,开放出可以让用户自定义的接口,那第三,第四个参数就是这个作用的。
来看下,spring 里默认是怎么做的,首先看下这两个接口的定义
public interface RequestCallback { /** * Gets called by {@link RestTemplate#execute} with an opened {@code ClientHttpRequest}. * Does not need to care about closing the request or about handling errors: * this will all be handled by the {@code RestTemplate}. * @param request the active HTTP request * @throws IOException in case of I/O errors */ void doWithRequest(ClientHttpRequest request) throws IOException; }
public interface ResponseExtractor<T> { /** * Extract data from the given {@code ClientHttpResponse} and return it. * @param response the HTTP response * @return the extracted data * @throws IOException in case of I/O errors */ T extractData(ClientHttpResponse response) throws IOException; }
很明显,这两个接口分别是在请求前,ClientHttpRequest请求前会作回调,而在请求结束后,又会调用ResponseExtractor去作请求结果解析的动作
再来看下方法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; }
而 getRequestFactory()在 InterceptingHttpAccessor 中被重载了
@Override public ClientHttpRequestFactory getRequestFactory() { ClientHttpRequestFactory delegate = super.getRequestFactory(); if (!CollectionUtils.isEmpty(getInterceptors())) { return new InterceptingClientHttpRequestFactory(delegate, getInterceptors()); } else { return delegate; } }
如果有设置拦截器,则返回的是一个InterceptingClientHttpRequestFactory类,而这个类创建的是
@Override protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) { return new InterceptingClientHttpRequest(requestFactory, this.interceptors, uri, httpMethod); }
Resttemplate 调用 的ClientHttpRequest.execute() 方法,其实就是InterceptingClientHttpRequest的方法,再来看下这个类的实现吧
@Override protected final ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException { InterceptingRequestExecution requestExecution = new InterceptingRequestExecution(); return requestExecution.execute(this, bufferedOutput); }
最终是通过InterceptingRequestExecution类来完成最终的调用
@Override public ClientHttpResponse execute(HttpRequest request, final byte[] body) throws IOException { if (this.iterator.hasNext()) { ClientHttpRequestInterceptor nextInterceptor = this.iterator.next(); return nextInterceptor.intercept(request, body, this); } else { ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), request.getMethod()); for (Map.Entry<String, List<String>> entry : request.getHeaders().entrySet()) { List<String> values = entry.getValue(); for (String value : values) { delegate.getHeaders().add(entry.getKey(), value); } } if (body.length > 0) { if (delegate instanceof StreamingHttpOutputMessage) { StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) delegate; streamingOutputMessage.setBody(new StreamingHttpOutputMessage.Body() { @Override public void writeTo(final OutputStream outputStream) throws IOException { StreamUtils.copy(body, outputStream); } }); } else { StreamUtils.copy(body, delegate.getBody()); } } return delegate.execute(); } }
从上面的代码可以很清晰的看到是怎么调用ClientHttpRequestInterceptor的
猜你喜欢
- 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)