Spring restTemplate
什么是RestTemplate
RestTemplate是Spring提供的用于访问Rest服务的客户端,提供了多种便捷访问远程HTTP服务的方法,能够大大提高客户端的编写效率。
项目中注入RestTemplate
首先在项目中添加依赖:
<!-- Jackson对自动解析JSON和XML格式的支持 -->
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency> <!-- HttpClient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
在注入RestTemplate的bean的时候,可以通过ClientHtppRequestFactory指定RestTemplate发起HTTP请求的底层实现所采用的类库。对此,ClientHttpRequestFactory接口主要提供了以下两种方法:
一种是SimpleClientHttpRequestFactory,使用J2SE提供的方式(即java.net包提供的方式)创建底层的HTTP请求连接。
另一种是使用HttpComponentsClientHttpRequestFactory方式,底层使用HttpClient访问远程的http服务,使用HttpClient可以配置连接池和证书等信息。
以下的两个方法都采用线程安全的单例(懒汉模式)
(1)SimpleClientHttpRequestFactory
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate; import javax.annotation.PostConstruct;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List; @Component
@Lazy(false)
public class SimpleRestClient { private static final Logger LOGGER = LoggerFactory.getLogger(SimpleRestClient.class); private static RestTemplate restTemplate; static {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setReadTimeout(5000);
requestFactory.setConnectTimeout(5000); // 添加转换器
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
messageConverters.add(new MappingJackson2HttpMessageConverter()); restTemplate = new RestTemplate(messageConverters);
restTemplate.setRequestFactory(requestFactory);
restTemplate.setErrorHandler(new DefaultResponseErrorHandler()); LOGGER.info("SimpleRestClient初始化完成");
} private SimpleRestClient() { } @PostConstruct
public static RestTemplate getClient() {
return restTemplate;
} }
(2)HttpComponentsClientHttpRequestFactory(推荐使用)
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit; import org.apache.http.Header;
import org.apache.http.client.HttpClient;
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.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
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.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.web.client.RestTemplate; @Configuration
public class RestTemplateConfig { /**
* 返回RestTemplate
* @param factory
* @return
*/
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory){
//消息转换器,Spring Boot环境可省略,只需要添加相关依赖即可
// List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
// messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
// messageConverters.add(new FormHttpMessageConverter());
// messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
// messageConverters.add(new MappingJackson2HttpMessageConverter()); RestTemplate restTemplate = new RestTemplate(factory);
// restTemplate.setMessageConverters(messageConverters); return restTemplate;
} /**
* ClientHttpRequestFactory接口的另一种实现方式(推荐使用),即:
* HttpComponentsClientHttpRequestFactory:底层使用Httpclient连接池的方式创建Http连接请求
* @return
*/
@Bean
public HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory(){
//Httpclient连接池,长连接保持30秒
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS); //设置总连接数
connectionManager.setMaxTotal(1000);
//设置同路由的并发数
connectionManager.setDefaultMaxPerRoute(1000); //设置header
List<Header> headers = new ArrayList<Header>();
headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.04"));
headers.add(new BasicHeader("Accept-Encoding", "gzip, deflate"));
headers.add(new BasicHeader("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3"));
headers.add(new BasicHeader("Connection", "keep-alive")); //创建HttpClient
HttpClient httpClient = HttpClientBuilder.create()
.setConnectionManager(connectionManager)
.setDefaultHeaders(headers)
.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)) //设置重试次数
.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy()) //设置保持长连接
.build(); //创建HttpComponentsClientHttpRequestFactory实例
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory(httpClient); //设置客户端和服务端建立连接的超时时间
requestFactory.setConnectTimeout(5000);
//设置客户端从服务端读取数据的超时时间
requestFactory.setReadTimeout(5000);
//设置从连接池获取连接的超时时间,不宜过长
requestFactory.setConnectionRequestTimeout(200);
//缓冲请求数据,默认为true。通过POST或者PUT大量发送数据时,建议将此更改为false,以免耗尽内存
requestFactory.setBufferRequestBody(false); return requestFactory;
} }
RestTemplate提供了很多方法,可以与HTTP方法对应。
| HTTP方法 | RestTemplate方法 | 说明 |
|---|---|---|
| DELETE | delete() | 在特定的URL上对资源执行HTTP DELETE操作 |
| GET |
getForEntity() getForObject() |
getForEntity():发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象。 getForObject():发送一个HTTP GET请求,返回根据响应体映射形成的对象 |
| POST |
postForEntity() postForLocation() postForObject() |
postForEntity(): POST数据到一个URL,返回的ResponseEntity包含了响应体所映射成的对象。 postForLocation(): POST数据到一个URL,返回新创建资源的URL。 postForObject(): POST数据到一个URL,返回根据响应体映射形成的对象 |
| PUT | put() | PUT资源到特定的URL |
| HEAD | headForHeaders() | 发送HTTP HEAD请求,返回包含特定资源URL的HTTP头 |
| OPTIONS | optionsForAllow() | 发送HTTP OPTIONS请求,返回对特定URL的Allow头信息 |
| PATCH and others |
exchange() execute() |
exchange(): 在URL上执行特定的HTTP方法,返回的ResponseEntity包含了响应体所映射成的对象 execute():在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象 |
接下来讲一下RestTemplate的这几个方法如何使用。
GET请求方式的两种方法
1. getForEntity()
三个getForEntity()方法的签名:
<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;
示例代码:
/**
* 测试Get请求返回详细信息,包括:响应正文、响应状态码、响应Header等
*/
@Test
public void testGetMethod3(){
//第一个参数为要调用的服务的地址,第二个参数为返回值的类型,第三和第四个参数时url中的传参
ResponseEntity<DemoObj> responseEntity = restTemplate.getForEntity("http://127.0.0.1:9090/rest/testJson2?id={1}&name={2}"
, DemoObj.class
, 1,"Tom"); DemoObj body = responseEntity.getBody();
int statusCodeValue = responseEntity.getStatusCodeValue();
HttpHeaders headers = responseEntity.getHeaders(); System.out.println("responseEntity.getBody():" + body);
System.out.println("responseEntity.getStatusCodeValue():" + statusCodeValue);
System.out.println("responseEntity.getHeaders():" + headers);
}
结果:
responseEntity.getBody():DemoObj [id=2, name=Tom Ret]
responseEntity.getStatusCodeValue():200
responseEntity.getHeaders():{Date=[Fri, 09 Feb 2018 06:22:28 GMT], Content-Type=[application/json;charset=utf-8], Transfer-Encoding=[chunked]}
再来看一个Map传参的例子:
@RequestMapping("/sayhello2")
public String sayHello2() {
Map<String, String> map = new HashMap<>();
map.put("name", "李四");
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/sayhello?name={name}", String.class, map);
return responseEntity.getBody();
}
当然,第一个参数也可以是URI而不是字符串,可以通过Spring中的UriComponents来构建uri即可。
@RequestMapping("/sayhello3")
public String sayHello3() {
UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://HELLO-SERVICE/sayhello?name={name}").build().expand("王五").encode();
URI uri = uriComponents.toUri();
ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);
return responseEntity.getBody();
}
2.getForObject()
getForObject()实际上是对getForEntity()的进一步封装,用法类似,唯一的区别就是getForObject()方法只返回请求类型的对象,而getForEntity()会返回请求的对象以及响应的Header,响应状态码等额外信息。
@RequestMapping("/book2")
public Book book2() {
Book book = restTemplate.getForObject("http://HELLO-SERVICE/getbook1", Book.class);
return book;
}
@Test
public void testGetMethod2(){
Map<String, String> uriVariables = new HashMap<String, String>();
uriVariables.put("var_id", "1");
uriVariables.put("var_name", "Tom"); DemoObj obj = restTemplate.getForObject("http://127.0.0.1:9090/rest/testJson2?id={var_id}&name={var_name}"
, DemoObj.class
, uriVariables); System.out.println(obj);
}
POST请求的三种方法
1. postForEntity()
POST请求和GET请求类似,也是三种方法:
<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;
看个示例:
@Test
public void testPostMethod2(){
DemoObj request = new DemoObj(1l, "Tim"); ResponseEntity<DemoObj> responseEntity = restTemplate.postForEntity("http://127.0.0.1:9090/rest/testJson1"
, request, DemoObj.class); DemoObj body = responseEntity.getBody();
int statusCodeValue = responseEntity.getStatusCodeValue();
HttpHeaders headers = responseEntity.getHeaders(); System.out.println("responseEntity.getBody():" + body);
System.out.println("responseEntity.getStatusCodeValue():" + statusCodeValue);
System.out.println("responseEntity.getHeaders():" + headers);
}
结果:
responseEntity.getBody():DemoObj [id=2, name=Tim Ret]
responseEntity.getStatusCodeValue():200
responseEntity.getHeaders():{Date=[Fri, 09 Feb 2018 06:32:02 GMT], Content-Type=[application/json;charset=utf-8], Transfer-Encoding=[chunked]}
2.postForObject()
@Test
public void testPostMethod1(){
DemoObj request = new DemoObj(1l, "Tim"); DemoObj obj = restTemplate.postForObject("http://127.0.0.1:9090/rest/testJson1"
, request, DemoObj.class); System.out.println(obj);
}
3.postForLocation()
postForLocation()也是提交新资源,提交成功之后,返回新资源的URI,postForLocation的参数和前面两种的参数基本一致,只不过该方法的返回值为Uri,这个只需要服务提供者返回一个Uri即可,该Uri表示新资源的位置。
PUT请求
在RestTemplate中,PUT请求可以通过put方法调用,put方法的参数和前面介绍的postForEntity方法的参数基本一致,只是put方法没有返回值而已。
@RequestMapping("/put")
public void put() {
Book book = new Book();
book.setName("红楼梦");
restTemplate.put("http://HELLO-SERVICE/getbook3/{1}", book, 99);
}
DELETE请求
@RequestMapping("/delete")
public void delete() {
restTemplate.delete("http://HELLO-SERVICE/getbook4/{1}", 100);
}
exchange()方法执行指定的HTTP请求
exchange()方法同上面的很多方法不同的是,它可以指定请求的HTTP方式。
@Test
public void testExchange(){
//设置header
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/x-zifangsky"); //设置参数
String requestBody = "1#Converter";
HttpEntity<String> requestEntity = new HttpEntity<String>(requestBody,headers); ResponseEntity<String> responseEntity = restTemplate.exchange("http://127.0.0.1:9090/convert"
, HttpMethod.POST, requestEntity, String.class); System.out.println("responseEntity.getBody():" + responseEntity.getBody());
System.out.println("responseEntity.getHeaders():" + responseEntity.getHeaders());
}
手动指定转换器
调用restful接口传递的数据是json格式的字符串,返回的响应也是json格式的字符串。
Spring restTemplate的更多相关文章
- Spring RestTemplate: 比httpClient更优雅的Restful URL访问, java HttpPost with header
{ "Author": "tomcat and jerry", "url":"http://www.cnblogs.com/tom ...
- Spring RestTemplate介绍
http://www.cnblogs.com/rollenholt/p/3894117.html RestTemplate 这篇文章打算介绍一下Spring的RestTemplate.我这边以前设计到 ...
- How to Send an HTTP Header With Every Request With Spring RestTemplate
In Know Which Apps Are Hitting Your Web Service, I showed how to write a servlet filter that enforce ...
- Spring RestTemplate详解
Spring RestTemplate详解 1.什么是REST? REST(RepresentationalState Transfer)是Roy Fielding 提出的一个描述互联系统架构风格 ...
- Spring RestTemplate中几种常见的请求方式GET请求 POST请求 PUT请求 DELETE请求
Spring RestTemplate中几种常见的请求方式 原文地址: https://blog.csdn.net/u012702547/article/details/77917939 版权声明 ...
- How to disable SSL certificate checking with Spring RestTemplate?(使用resttemplate访问https时禁用证书检查)
How to disable SSL certificate checking with Spring RestTemplate?(使用resttemplate访问https时禁用证书检查) **** ...
- Spring RestTemplate 小结
关于RestTemplate 首先,你可以把它理解为一个发起请求并接收响应的工具类(功能类似浏览器). 其次,它其实是一个壳,具体还是通过调用别的接口来实现(如jdk自带的连接,或者HttpClien ...
- spring RestTemplate用法详解
spring RestTemplate用法详解 spring 3.2.3 框架参考有说明 21.9 Accessing RESTful services on the Client
- 使用HttpClient4来构建Spring RestTemplate
Spring RestTemplate简单说明 现在REST服务已经很普及了,在我们的程序中,经常会需要调用REST API,这时候会有很多选择,原始一点的JDK自带的,再进一步点使用HttpClie ...
- spring restTemplate 用法
发出get请求,方式一 String url = serverUrl+"/path/path?id={id}"; int i = restTemplate.getForObject ...
随机推荐
- 《CDN 之我见》原理篇——CDN的由来与调度
CDN是将源站内容分发至全国所有的节点,从而缩短用户查看对象的延迟,提高用户访问网站的响应速度与网站的可用性的技术.它能够有效解决网络带宽小.用户访问量大.网点分布不均等问题. 为了让大家更全面的了解 ...
- Hybris阶段总结(2)hybris架构
年前总结一下这两个星期在SAP实习学到的一些东西 先上图: 从底往上总结,之后会有个小例子来解释一下 1.Persistence layer 就是作为hybris所连接的数据库这一层,其中hybr ...
- 铁乐学Python_day11_闭包函数
一.[函数名] 1)函数名本质上它也是一种变量,特殊的变量: (碰到同名其它变量,依照从上往下的代码执行赋值.) 单独打印函数名,输出的是它对应的内存地址: 例: def funcl(): print ...
- MySQL 索引的介绍与应用
Mysql索引 一. mysql 索引 索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息. 二:MySQL索引类型 按存储结构区分:聚集索引(又称聚类索引,簇 ...
- September 08th 2017 Week 36th Friday
Death is so terribly final, while life is full of possibilities. 死亡是冰冷可怕的绝境,而或者却充满了无限的可能. It isn't t ...
- December 01st 2016 Week 49th Thursday
Life is a maze and love is a riddle. 生活是个迷宫,爱情是个谜语. I am lost in both. Can you provide me some guida ...
- UE4中动画蒙太奇的合成
在游戏中的技能施法动作是可以通过软件合成的,笔者在这里介绍一种用UE4合成多个动画的操作. 在UE4中角色的动作可以由多种方式达成,一种是混合空间,例如角色的跑动和跳跃,其中的动作是由状态机控制的,原 ...
- python处理数据(二)
处理PDF文件 PyPDF2简介 作为 PDF 工具包构建的纯 python 库. 它可以:提取文档信息(标题,作者,... ...)一页一页地分割文件一页一页地合并文件裁剪页面将多个页面合并成一个页 ...
- vue项目用nodejs实现模拟数据方法
1)在项目根目录(如demo)中创建一个文件夹,如base,将项目中所有的前端文件全部放到base文件夹中,此时项目demo下只有一个文件夹base 2)通过cmd进入命令窗口,直接执行npm ins ...
- 基础拾遗 C# Json 与对象相互转换
方法一.JavaScriptSerializer 方法二.JsonConvert 示例: Web API项目 1.新建 Model: namespace WebApi{ public class Pr ...