SpringBoot 学习之RestTemplate
前言
概述
RestTemplate 是 Spring 提供的用于访问Rest服务的客户端,RestTemplate 提供了多种便捷访问远程Http服务的方法,它简化了与 http 服务的通信方式,统一了 RESTful 的标准,封装了 http 链接, 我们只需要传入 url 及返回值类型即可。相较于之前常用的 HttpClient,RestTemplate 是一种更优雅的调用 RESTful 服务的方式。默认情况下,RestTemplate 默认依赖 jdk 的HTTP连接工具(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为例如 Apache HttpComponents、Netty或OkHttp等其它HTTP library。
该模板类的主要切入点为以下几个方法(其根据HTTP的六个方法制定六个主要方法)
Post | postForLocation | POST 数据到一个URL,返回新创建资源的URL |
postForEntity | POST 数据到一个URL,返回包含一个对象的ResponseEntity | |
postForObject | POST 数据到一个URL,返回根据响应体匹配形成的对象 | |
Get | getForObject | 发送一个HTTP GET请求,返回的请求体将映射为一个对象 |
getForEntity | 发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象 | |
Delete | delete | |
head | headForHeaders | |
put | put | |
any | exchange | |
execute | 所有的get、post、delete、put、options、head、exchange方法最终调用的都是excute方法 |
对外开放的接口
- [x] 在内部,RestTemplate默认使用HttpMessageConverter实例将HTTP消息转换成POJO或者从POJO转换成HTTP消息
RestTemplate是 spring 的一个 rest 客户端,在 spring-web 这个包下,spring boot的依赖如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
RestTemplate只是对其它Rest客户端的一个封装,本身并没有自己的实现。在没有第三方依赖的情况下其默认实现是HttpURLConnection(集成了URLConnection),这是JDK自带的REST客户端实现。现在来看下其它最常用的几种客户端的引入
SimpleClientHttpRequestFactory(封装URLConnection)
HttpComponentsClientHttpRequestFactory(封装HttpClient)
OkHttp3ClientHttpRequestFactory(封装OKHttp)
其切换与使用也很简单,在pom中引入相应依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
初始化RestTemplate
在Config中的配置:
package org.dllwh.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
return restTemplate;
}
@Bean("urlConnection")
public RestTemplate urlConnectionRestTemplate() {
RestTemplate restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory());
return restTemplate;
}
@Bean("httpClient")
public RestTemplate httpClientRestTemplate() {
RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
return restTemplate;
}
@Bean("OKHttp3")
public RestTemplate OKHttp3RestTemplate() {
RestTemplate restTemplate = new RestTemplate(new OkHttp3ClientHttpRequestFactory());
return restTemplate;
}
}
使用的时候一般都会只选择其中的一种,所以上面的几种配置任选其一。这里仅仅只是演示说明
RestTemplate前先得做一些初始化处理,比如指定http客户端工厂类、设置超时时间、响应参数转换器等。以 HttpComponents 为例说明。
package org.dllwh.config;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.Header;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Configuration
public class RestTemplateConfig {
/** 建立连接的超时时间 */
private static int connectTimeout = 20000;
/** 连接不够用的等待时间 */
private static int requestTimeout = 20000;
/** 每次请求等待返回的超时时间 */
private static int socketTimeout = 30000;
/** 每个主机最大连接数 */
private static int defaultMaxPerRoute = 100;
/** 最大连接数 */
private static int maxTotalConnections = 300;
@Bean
public RestTemplate buildRestTemplate(ClientHttpRequestFactory factory) {
RestTemplate restTemplate = new RestTemplate(factory);
restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
return restTemplate;
}
/**
* @方法描述:创建HTTP客户端工厂
* @return
*/
@Bean
public HttpComponentsClientHttpRequestFactory createFactory() {
// httpClient连接配置
SSLContextBuilder builder = new SSLContextBuilder();
try {
TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
public boolean isTrusted(X509Certificate[] chain, String authType) {
return true;
}
};
builder.loadTrustMaterial(null, acceptingTrustStrategy);
} catch (Exception e) {
log.error("Pooling Connection Manager Initialisation failure because of " + e.getMessage(), e);
}
SSLConnectionSocketFactory socketFactory = null;
try {
socketFactory = new SSLConnectionSocketFactory(builder.build(), NoopHostnameVerifier.INSTANCE);
} catch (KeyManagementException | NoSuchAlgorithmException e) {
log.error("Pooling Connection Manager Initialisation failure because of " + e.getMessage(), e);
}
// 注册http和https请求
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", socketFactory).build();
// 开始设置连接池
PoolingHttpClientConnectionManager phccm = new PoolingHttpClientConnectionManager(registry);
// 最大连接数
phccm.setMaxTotal(maxTotalConnections);
// 同路由并发数
phccm.setDefaultMaxPerRoute(defaultMaxPerRoute);
HttpClientBuilder httpClientBuilder = HttpClients.custom();
httpClientBuilder.setSSLSocketFactory(socketFactory);
httpClientBuilder.setConnectionManager(phccm);
httpClientBuilder.setConnectionManagerShared(true);
// 重试次数,默认是3次,没有开启
httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true));
// 保持长连接配置,需要在头添加Keep-Alive
httpClientBuilder.setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE);
List<Header> headers = new ArrayList<>();
headers.add(new BasicHeader("User-Agent",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.59 Safari/537.36"));
headers.add(new BasicHeader("Connection", "keep-alive"));
httpClientBuilder.setDefaultHeaders(headers);
CloseableHttpClient httpClient = httpClientBuilder.build();
// httpClient连接配置,底层是配置RequestConfig
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setHttpClient(httpClient);
// 连接超时
factory.setConnectTimeout(connectTimeout);
// 数据读取超时时间,即SocketTimeout
factory.setReadTimeout(socketTimeout);
// 连接不够用的等待时间,不宜过长,必须设置,比如连接不够用时,时间过长将是灾难性的
factory.setConnectionRequestTimeout(requestTimeout);
// 缓冲请求数据,默认值是true。通过POST或者PUT大量发送数据时,建议将此属性更改为false,以免耗尽内存。
factory.setBufferRequestBody(false);
return factory;
}
}
GET请求
getForEntity
getForEntity() 的返回值类型 ResponseEntity,通过源码可以看到它继承了 HttpEntity ,封装了返回的响应信息,包括 响应状态、响应头、响应体等,获取Http请求的全部信息。
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)
throws RestClientException;
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
throws RestClientException;
<T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException;
ResponseEntity response = restTemplate.getForEntity("http://localhost:8081/server",String.class);
response.getHeaders(); //响应头
response.getStatusCode(); //响应码
response.getBody(); //响应体,即前面的result
- [ ] 第1个参数:要调用的服务的地址
- [ ] 第2个参数:表示希望返回的body类型
- [ ] 第3个以及以后参数:表示请求参数
- 可以使用map来封装请求参数,并作为getForObject的第三个参数,同时修改url如下,map中的"1"会替换url中的{1},"2"会替换url中的{2}
Map map = new HashMap();
map.put("1", "hello");
map.put("2", "world");
String result = restTemplate.getForObject("http://localhost:8081/server?param1={1}¶m2={2}",
String.class, map);
- 也可以直接将要传递的值放到getForObject方法的参数结尾,数量不限,它会按顺序替换{1}和{2}
String result = restTemplate.getForObject("http://localhost:8081/server?param1={1}¶m2={2}",
String.class, "hello", "world");
getForObject
getForObject 和 getForEntity 用法几乎相同,实际上是对getForEntity函数的进一步封装,返回值返回的是 响应体,省去了我们 再去 getBody()。
POST请求
postForObject
postForObject指post请求,并返回一个Object对象
String response = restTemplate.postForObject("http://localhost:8081/server?param1={1}¶m2={2}",
null, String.class, "hello", "world");
- [ ] 第1个参数就是getForObject第1个参数。
- [ ] 第2个参数为null,实际上是HttpEntity
- [ ] 第3个参数就是getForObject第2个参数
- [ ] 第4个及以后的参数就是getForObject第3个及以后的参数
postForObject除了第2个参数为null,其它地方用法和getForObject是一模一样的。但是post请求传参通常不是写在url上实现的,而是放在请求体中。此时,就需要使用第2个参数来传参,同时可省略第4个参数的url传参
Map map = new HashMap();
map.put("param1", "hello");
map.put("param2", "world");
String response = restTemplate.postForObject("http://localhost:8081/server", map, String.class);
- [x] 注意,服务端端接收不同参数时,语法也有所不同
public String server(@RequestBody Map map,String param1,String param2)
postForEntity
<T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType,
Object... uriVariables) throws RestClientException;
<T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType,
Map<String, ?> uriVariables) throws RestClientException;
<T> ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType)
throws RestClientException;
postForLocation
PUT请求
在RestTemplate中,PUT请求可以通过put方法调用,put方法的参数和前面介绍的postForEntity方法的参数基本一致,只是put方法没有返回值而已
@RequestMapping("put")
public void put() {
restTemplate.put("http://http://localhost:8081/server/put/?userName={1}", '独泪了无痕');
}
DELETE请求
delete请求我们可以通过delete方法调用来实现
@RequestMapping("delete")
public void delete() {
restTemplate.delete("http://localhost:8081/server/delete/{1}", 100);
}
Exchange请求
exchange()方法跟上面的getForObject()、getForEntity()、postForObject()、postForEntity()等方法不同之处在于它可以指定请求的HTTP类型。
需要注意的一点是对于返回结果为204 no content,这种没有返回值的请求,RestTemplate会抛错,有需要的话可以使用httpClient的fluent
Excute请求
excute() 的用法与 exchange() 大同小异了,它同样可以指定不同的 HttpMethod,不同的是它返回的对象是响应体所映射成的对象 ,而不是 ResponseEntity 。
转载于:https://my.oschina.net/u/1030471/blog/3006333
相关推荐
SpringBoot系列之RestTemplate使用示例,博主之前经常对接一些接口,所以发现写一些http请求比较麻烦,学习springboot的过程知道可以用 RestTemplate来做http请求,RestTemplate 是 Spring Framework 框架封装的基于...
主要介绍了Springboot集成restTemplate过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
该示例结合Swagger生成在线API,MyBatis Plus快速分页查询、RestTemplate实现远程访问服务端接口等基于SpringBoot框架的demo示例,对大家学习SpringCloud打下良好基础
在学习过程中,结合具体的代码示例和实际操作,将会使理解更加深刻。遗憾的是,文件名"girl"并没有直接关联到SpringBoot测试的知识点,但可能指的是一个示例项目或者测试用例的名字。在实践中,这样的命名可以帮助...
总的来说,"springboot038"项目展示了如何利用SpringBoot框架构建一个完整的网上租赁系统,涵盖了从用户交互到后台管理的多个层面,对于理解和学习SpringBoot的实际应用具有很高的参考价值。通过深入研究这个项目,...
Springboot可以通过RestTemplate或WebClient来调用这些API,实现在线支付。此外,为了保证交易安全,系统还需要处理支付状态的同步和异步回调,这部分通常需要设计合理的消息队列和监听机制,例如使用RabbitMQ或...
HTTP通信则常常涉及到与外部服务的交互,SpringBoot的RestTemplate或者WebClient可以方便地发送HTTP请求。此外,自定义拦截器或者Filter可以实现请求和响应的拦截,进行统一的日志记录或权限验证。 最后,字符串...
在SpringBoot和Mybatis结合的开发环境中,遇到的问题和学习的新知识主要集中在前端与后端的数据交互、控制器层的处理以及API调用等方面。以下是对这些知识点的详细说明: 1. **前端Ajax传参**:前端通过Ajax进行...
这通常涉及到HTTP请求的发送和解析,SpringBoot的RestTemplate或者WebClient可提供支持。 6. **前端界面**:虽然SpringBoot主要关注后端,但该项目可能包含Vue、React或Angular等前端框架的代码,用于构建用户友好...
通过此案例,你可以学习到如何在SpringBoot中集成MyBatis和Dubbo,理解微服务架构的设计思想,以及如何在实际开发中运用这些技术解决复杂的问题。同时,你还可以掌握如何管理和调试分布式系统,提升自己的开发和运维...
通过这个SpringBoot集成OCR功能的示例项目,开发者可以学习到如何将OCR技术融入到Spring Boot应用中,提升应用的智能化程度,从而提高工作效率和用户体验。同时,这也是一个了解和实践Java Web开发、RESTful API调用...
这可能需要调用第三方API获取疫情数据,使用SpringBoot的RestTemplate或者WebClient来实现API的调用。 4. 通信模块:实现用户之间的消息传递,可以采用WebSocket技术,SpringBoot提供了对WebSocket的支持。 5. ...
《基于SpringBoot的社区团购系统源码解析》 在当今数字化时代,社区团购作为一种...通过深入学习和分析源码,开发者不仅能掌握SpringBoot的核心特性,还能了解社区团购业务的运作流程,为今后的项目开发积累宝贵经验。
SpringBoot整合Eureka是构建微服务架构中的关键一环,Spring Boot简化了Spring应用程序的启动和配置,而Eureka则是Netflix开源的微服务组件,主要负责服务注册与发现。本学习资料聚焦于如何将这两者结合,以实现高效...
《基于SpringBoot的数字商城管理子系统源码...通过阅读和学习这个源码,开发者不仅可以了解SpringBoot的实践应用,还能学习到如何设计和实现一个完整的电商后台系统。对于提升自己的技术能力和项目经验具有很大的帮助。
基于SpringBoot+SpringCloud的微服务大型在线学习平台实现【服务端源码+数据库】.zip 项目介绍 学成在线就是一个在线学习平台,类似慕课网以及腾讯学堂,是专门针对IT行业进行在线学习的平台。 学成在线采用B2B2C的...
总而言之,这个压缩包提供了一个完整的、基于SpringBoot的点餐平台实现,对于学习SpringBoot开发、理解微服务架构以及Java Web开发流程都有很高的参考价值。通过研究这个源码,开发者可以深入理解SpringBoot的原理,...
在本项目中,"springboot做的天气查看及jps定位"是一个使用Spring Boot框架构建的应用,它整合了天气查询功能并结合了Java进程状态检查工具(JPS)。这个应用展示了Spring Boot如何优雅地将多种服务集成在一起,为...
总之,"SpringBoot酒店管理系统"项目提供了一个实践SpringBoot技术的绝佳平台,通过对这个系统的分析和学习,开发者不仅可以掌握SpringBoot的核心技术,还能了解到如何将这些技术应用于实际的业务场景,提升自己的...