什么是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的更多相关文章

  1. Spring RestTemplate: 比httpClient更优雅的Restful URL访问, java HttpPost with header

    { "Author": "tomcat and jerry", "url":"http://www.cnblogs.com/tom ...

  2. Spring RestTemplate介绍

    http://www.cnblogs.com/rollenholt/p/3894117.html RestTemplate 这篇文章打算介绍一下Spring的RestTemplate.我这边以前设计到 ...

  3. 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 ...

  4. Spring RestTemplate详解

    Spring RestTemplate详解   1.什么是REST? REST(RepresentationalState Transfer)是Roy Fielding 提出的一个描述互联系统架构风格 ...

  5. Spring RestTemplate中几种常见的请求方式GET请求 POST请求 PUT请求 DELETE请求

    Spring RestTemplate中几种常见的请求方式 原文地址: https://blog.csdn.net/u012702547/article/details/77917939   版权声明 ...

  6. How to disable SSL certificate checking with Spring RestTemplate?(使用resttemplate访问https时禁用证书检查)

    How to disable SSL certificate checking with Spring RestTemplate?(使用resttemplate访问https时禁用证书检查) **** ...

  7. Spring RestTemplate 小结

    关于RestTemplate 首先,你可以把它理解为一个发起请求并接收响应的工具类(功能类似浏览器). 其次,它其实是一个壳,具体还是通过调用别的接口来实现(如jdk自带的连接,或者HttpClien ...

  8. spring RestTemplate用法详解

    spring RestTemplate用法详解 spring 3.2.3 框架参考有说明 21.9 Accessing RESTful services on the Client

  9. 使用HttpClient4来构建Spring RestTemplate

    Spring RestTemplate简单说明 现在REST服务已经很普及了,在我们的程序中,经常会需要调用REST API,这时候会有很多选择,原始一点的JDK自带的,再进一步点使用HttpClie ...

  10. spring restTemplate 用法

    发出get请求,方式一 String url = serverUrl+"/path/path?id={id}"; int i = restTemplate.getForObject ...

随机推荐

  1. python常见释疑(有别于报错)(不定时更新)

    文:铁乐与猫 01.在cmd运行py脚本后,直接回到了提示符,没有任何输出,看起来像是并没有运行一样. 答:你的感觉很可能是对的,但脚本很可能己经正常运行,只是你的代码里面很可能没有给出print提示 ...

  2. 【http学习杂记】2017年7月14日

    1. 连接超时 连接超时是tcp协议层次, 此时服务器还没有处理请求数据,也就是说服务器的逻辑开没有执行 2. 请求超时 请求超时属于服务器已经连接成功并开始处理,但是时间比较长,大于你设置的请求超时 ...

  3. python第二十一课——str中的常用函数(重要)

    演示str中常用的一些函数: 1.join():将容器对象以某种特定的格式(字符串)进行拼接组合,最后以字符串的形式返回 lt=['i','love','you','very','much'] str ...

  4. python第十八课——常用内置函数

    常用内置函数:round(): print(round(3.14),round(3.99)) print(round(3145.926,-2),round(413.575,2)) abs(): pri ...

  5. 1208. [HNOI2004]宠物收养场【平衡树-splay】

    Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望领养到自己满意的宠物,阿Q根据领养者的要求通过他自己发明的一个特 ...

  6. ResultJsonInfo<T>

    using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace QY.We ...

  7. Linux - Confluence搭建

    0. 摘要 Confluence自身携带内置数据库,对于生产环境建议搭建外置数据库,Confluence通过相应驱动连接上.并操作数据库.Confluence支持多种数据库,本文采用MySQL. 1. ...

  8. ajax跨域调用webservice例子

    [WebMethod(Description = "这是一个描述")] public void GetTIM() { try { SqlDataAdapter da = new S ...

  9. virtualbox+vagrant学习-2(command cli)-10-vagrant Port命令

    Port 格式: vagrant port [options] [name|id] 端口命令显示映射到主机端口的客户端口的完整列表 userdeMacBook-Pro:~ user$ vagrant ...

  10. 常用命令 tcl & shell

    TCL 常用命令: 1. 当前时间  [exec  date  +%m%d_%H%M]   (实际是调用shell命令 date),比如在 icc 中保存cell 时可以用:save_mw_cel   ...