目錄
01. RestTemplate簡介
A). 簡要說明
B). RestTemplate有兩個構造方法
C). ClientHttpRequestFactory的兩種實作
02. Spring的RestTemplate對Post/Get的常用接口
A). Post請求API
B). Get請求API
03. 配置及使用
A). 配置檔案
B). 測試使用
附錄及示例:
A). pom.xml
B). RestClient.java / spring-restTemplate.xml
C). TestGetMain.java
D). TestPostMain.java
附錄二, httpClient參考網址
01. RestTemplate簡介
A). 簡要說明
RestTemplate是Spring提供的用于通路Rest服務的用戶端, RestTemplate提供了多種便捷通路遠端Http服務的方法, 能夠大大提高用戶端的編寫效率.
B). RestTemplate有兩個構造方法
分别是:
a). 第一個構造方法為預設初始化, 無法控制逾時時間;
b). 第二個構造方法可以傳入ClientHttpRequestFactory參數, 設定該工廠類的timeout屬性可以控制逾時時間;
結論: 由于我們經常需要對請求逾時進行設定并進行後續處理, 是以選用第二個構造方法.
C). ClientHttpRequestFactory的兩種實作
a). SimpleClientHttpRequestFactory: 使用J2SE提供的方式(java.net包提供的方式)建立底層的Http請求連接配接;
b). HttpComponentsClientHttpRequestFactory: 使用HttpClient通路遠端的Http服務, 使用HttpClient可以配置連接配接池和證書等資訊.
注意: RestTemplate預設是使用SimpleClientHttpRequestFactory,内部是調用jdk的HttpConnection, 預設逾時為-1
02. Spring的RestTemplate對Post/Get的常用接口
A). Post請求API
public <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables) throws RestClientException
public <T> T postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException
public <T> T postForObject(URI url, Object request, Class<T> responseType) throws RestClientException
B). Get請求API
public <T> T getForObject(String url, Class<T> responseType, Object... urlVariables) throws RestClientException
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> urlVariables) throws RestClientException
public <T> T getForObject(URI url, Class<T> responseType) throws RestClientException
例如:
String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", String.class,"42", "21");
String message = restTemplate.getForObject("http://localhost:8080/yongbarservice/appstore/appgoods/restTemplate?name=zhaoshijie&id=80", String.class);
Map<String, String> vars = Collections.singletonMap("hotel", "42");
String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
03. 配置及使用
A). 配置檔案
pom.xml
RestClient.java
spring-restTemplate.xml
B). 測試使用
TestGetMain.java
TestPostMain.java
附錄及示例:
A). pom.xml
主要關注需要引入的jar包, jar包版本過低會出現很多問題, 什麼版本合适請自行處理; 懶人請按如下或更高版本操作...
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cntv.learn</groupId>
<artifactId>restTemplate_v3.0</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<junit.version>4.12</junit.version>
<slf4j.version>1.7.25</slf4j.version>
<spring.version>4.3.18.RELEASE</spring.version>
<jackson.version>2.9.4</jackson.version>
<fastjson.version>1.2.47</fastjson.version>
<httpclient.version>4.5.2</httpclient.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- 映入JSON -->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-xml -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>
</dependencies>
</project>
B). RestClient.java / spring-restTemplate.xml
根據使用工廠類的不同(SimpleClientHttpRequestFactory, 或者 HttpComponentsClientHttpRequestFactory), 配置
restTemplate分為兩種, 具體配置如下:
01-01. spring-restTemplate.xml 使用 SimpleClientHttpRequestFactory
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byName" default-lazy-init="true">
<!--方式一、使用jdk的實作-->
<bean id="ky.requestFactory" class="org.springframework.http.client.SimpleClientHttpRequestFactory">
<property name="readTimeout" value="10000"/>
<property name="connectTimeout" value="5000"/>
</bean>
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg ref="ky.requestFactory"/>
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
</beans>
01-02. RestClient.java 使用 SimpleClientHttpRequestFactory
package com.cntv.learn.client;
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;
/**
* @author LiuDong
* @msg 第一種以類的方式擷取restTemplate
*/
@Component
@Lazy(false)
public class RestClient {
private static final Logger LOGGER = LoggerFactory.getLogger(RestClient.class);
private static RestTemplate restTemplate;
static {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setReadTimeout(5000);
requestFactory.setConnectTimeout(5000);
// 添加轉換器
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
messageConverters.add(new MappingJackson2HttpMessageConverter());
messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
restTemplate = new RestTemplate(messageConverters);
restTemplate.setRequestFactory(requestFactory);
restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
LOGGER.info("SimpleRestClient初始化完成");
}
private RestClient() {
}
@PostConstruct
public static RestTemplate getClient() {
return restTemplate;
}
}
02-01. spring-restTemplate.xml 使用 HttpComponentsClientHttpRequestFactory
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byName" default-lazy-init="true">
<!--方式二: 使用httpclient的實作,帶連接配接池(在httpclient4.3版本後才有)-->
<bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder" factory-method="create">
<property name="connectionManager">
<bean class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager">
<!--整個連接配接池的并發-->
<property name="maxTotal" value="50"/>
<!--每個主機的并發-->
<property name="defaultMaxPerRoute" value="50"/>
</bean>
</property>
<!--開啟重試-->
<property name="retryHandler">
<bean class="org.apache.http.impl.client.DefaultHttpRequestRetryHandler">
<constructor-arg value="2"/>
<constructor-arg value="true"/>
</bean>
</property>
<property name="defaultHeaders">
<list>
<bean class="org.apache.http.message.BasicHeader">
<constructor-arg value="Content-Type"/>
<constructor-arg value="text/html;charset=UTF-8"/>
</bean>
<bean class="org.apache.http.message.BasicHeader">
<constructor-arg value="Accept-Encoding"/>
<constructor-arg value="gzip,deflate"/>
</bean>
<bean class="org.apache.http.message.BasicHeader">
<constructor-arg value="Accept-Language"/>
<constructor-arg value="zh-CN"/>
</bean>
</list>
</property>
</bean>
<bean id="httpClient" factory-bean="httpClientBuilder" factory-method="build"/>
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list value-type="org.springframework.http.converter.HttpMessageConverter">
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes" value="application/json;charset=UTF-8" />
</bean>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<!--<property name="supportedMediaTypes" value="text/html;charset=UTF-8" />-->
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
<property name="requestFactory">
<bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<constructor-arg ref="httpClient"/>
<!--連接配接時間(毫秒)-->
<property name="connectTimeout" value="20000"/>
<!--讀取時間(毫秒)-->
<property name="readTimeout" value="20000"/>
</bean>
</property>
</bean>
</beans>
02-02. RestClient.java 使用 HttpComponentsClientHttpRequestFactory
package com.cntv.learn.client;
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.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
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.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;
import java.util.concurrent.TimeUnit;
@Component
@Lazy(false)
public class RestClient {
private static final Logger LOGGER = LoggerFactory.getLogger(RestClient.class);
private static RestTemplate restTemplate;
static {
// 長連接配接保持30秒
PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);
// 總連接配接數
pollingConnectionManager.setMaxTotal(1000);
// 同路由的并發數
pollingConnectionManager.setDefaultMaxPerRoute(1000);
HttpClientBuilder httpClientBuilder = HttpClients.custom();
httpClientBuilder.setConnectionManager(pollingConnectionManager);
// 重試次數,預設是3次,沒有開啟
httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(2, true));
// 保持長連接配接配置,需要在頭添加Keep-Alive
httpClientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy());
List<Header> headers = new ArrayList<>();
headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36"));
headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate"));
headers.add(new BasicHeader("Accept-Language", "zh-CN"));
headers.add(new BasicHeader("Connection", "Keep-Alive"));
httpClientBuilder.setDefaultHeaders(headers);
HttpClient httpClient = httpClientBuilder.build();
// httpClient連接配接配置,底層是配置RequestConfig
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
// 連接配接逾時
clientHttpRequestFactory.setConnectTimeout(5000);
// 資料讀取逾時時間,即SocketTimeout
clientHttpRequestFactory.setReadTimeout(5000);
// 連接配接不夠用的等待時間,不宜過長,必須設定,比如連接配接不夠用時,時間過長将是災難性的
clientHttpRequestFactory.setConnectionRequestTimeout(200);
// 緩沖請求資料,預設值是true。通過POST或者PUT大量發送資料時,建議将此屬性更改為false,以免耗盡記憶體。
// clientHttpRequestFactory.setBufferRequestBody(false);
// 添加内容轉換器
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
messageConverters.add(new MappingJackson2HttpMessageConverter());
messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
restTemplate = new RestTemplate(messageConverters);
restTemplate.setRequestFactory(clientHttpRequestFactory);
restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
LOGGER.info("RestClient初始化完成");
}
private RestClient() {
}
@PostConstruct
public static RestTemplate getClient() {
return restTemplate;
}
}
C). TestGetMain.java
參照 調用Get請求接口API , spring-restTemplate.xml的調用如下:
package com.cntv.learn;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
/**
* @author : LiuDong
* @description : 莉莉
* @date : Created in 2018/7/10 15:05
*/
public class TestGetMain {
private static final Logger LOGGER = LoggerFactory.getLogger(TestGetMain.class);
public static void main(String[] args) {
// 擷取app上下文
String configLocation = "config/spring-restTemplate.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
// 擷取userService對象
RestTemplate restTemplate = (RestTemplate) context.getBean("restTemplate");
testRestTemplateForPostV2(restTemplate);
}
/**
* 方式一: 調用Get請求
* text請求, json響應
* @param restTemplate 調用http請求
*/
private static void testRestTemplateForPostV2(RestTemplate restTemplate) {
// 1-1. . 請求參數
// Map<String, String> urlVariables = new HashMap<>();
// urlVariables.put("host", ""www.lala.com");
String urlVariables = "www.lala.com";
// 1-2. 請求位址
String url = "http://{host}/projectName/saveSxPolicy?username=ss&age=18";
// 2-0. 調用
JSONObject exchange;
try {
exchange = restTemplate.getForObject(url, JSONObject.class, urlVariables);
LOGGER.info(exchange.toString());
System.out.println(exchange.toString());
} catch (RestClientException e) {
LOGGER.info("請求失敗...");
System.out.println("請求失敗: " + e.getMessage());
}
}
}
D). TestPostMain.java
參照 調用Post請求接口API , spring-restTemplate.xml的調用如下:
package com.cntv.learn;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
/**
* @author : LiuDong
* @description : 莉莉
* @date : Created in 2018/7/10 15:05
*/
public class TestPostMain {
private static final String TOKEN = "3ffe8a64-10cf-4d0e-b7f3-0efc05824376";
private static final Logger LOGGER = LoggerFactory.getLogger(TestPostMain.class);
public static void main(String[] args) {
// 擷取app上下文
String configLocation = "config/spring-restTemplate.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
// 擷取userService對象
RestTemplate restTemplate = (RestTemplate) context.getBean("restTemplate");
testRestTemplateForPostV1(restTemplate);
testRestTemplateForPostV2(restTemplate);
}
/**
* 方式一: 調用JSON的Post請求
* @param restTemplate 調用http請求
*/
private static void testRestTemplateForPostV1(RestTemplate restTemplate) {
// 1-1. 請求頭資訊
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
// 1-2. . 請求參數
JSONObject postParameters = new JSONObject();
// ParameterRo postParameters = new ParameterRo();
// Map<String, String> postParameters = new HashMap<>(3);
postParameters.put("openid", "opentid_test");
HttpEntity<JSONObject> requestEntity = new HttpEntity<>(postParameters, headers);
// 1-3. 請求位址
String url = "http://www.lala.com/projectPoth/saveIPAndAddress";
// 2-0. 調用
JSONObject exchange;
try {
exchange = restTemplate.postForObject(url, requestEntity, JSONObject.class);
LOGGER.info(exchange.toString());
System.out.println(exchange.toString());
} catch (RestClientException e) {
LOGGER.info("請求失敗...");
System.out.println("請求失敗: " + e.getMessage());
}
}
/**
* 方式二: 調用普通Post請求(簡單版)
* text請求, json響應
* @param restTemplate 調用http請求
*/
private static void testRestTemplateForPostV2(RestTemplate restTemplate) {
// 1-1. . 請求參數
MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<>();
requestEntity.set("token", TOKEN);
// 1-2. 請求位址
String url = "http://www.lala.com/project/searchGroupOrgList";
// 2-0. 調用
JSONArray exchange;
try {
exchange = restTemplate.postForObject(url, requestEntity, JSONArray.class);
LOGGER.info(exchange.toString());
System.out.println(exchange.toString());
} catch (RestClientException e) {
LOGGER.info("請求失敗...");
System.out.println("請求失敗: " + e.getMessage());
}
}
/**
* 模拟請求參數
*/
static private class ResponseVo {
private String code = "0";
private String errMsg = "請求失敗...";
private Object data;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
}
附錄二, httpClient參考網址
httpclient調用http請求學習: https://www.cnblogs.com/fengli9998/p/8028250.html