什么是RestTemplate?
RestTemplate是Spring提供的用於訪問Rest服務的客戶端,RestTemplate提供了多種便捷訪問遠程Http服務的方法,能夠大大提高客戶端的編寫效率。
調用RestTemplate的默認構造函數,RestTemplate對象在底層通過使用java.net包下的實現創建HTTP 請求,可以通過使用ClientHttpRequestFactory指定不同的HTTP請求方式。
ClientHttpRequestFactory接口主要提供了兩種實現方式
- 一種是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)創建底層的Http請求連接。
- 一種方式是使用HttpComponentsClientHttpRequestFactory方式,底層使用HttpClient訪問遠程的Http服務,使用HttpClient可以配置連接池和證書等信息。
xml配置的方式
請查看RestTemplate源碼了解細節,知其然知其所以然!
RestTemplate默認是使用SimpleClientHttpRequestFactory,內部是調用jdk的HttpConnection,默認超時為-1
@Autowired
RestTemplate simpleRestTemplate
@Autowired
RestTemplate restTemplate
基於jdk的spring的RestTemplate
<?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="simpleRestTemplate" 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>
使用Httpclient連接池的方式
<?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的實現,帶連接池--> <bean id="ky.pollingConnectionManager" class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager"> <!--整個連接池的並發--> <property name="maxTotal" value="1000" /> <!--每個主機的並發--> <property name="defaultMaxPerRoute" value="1000" /> </bean> <bean id="ky.httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder" factory-method="create"> <property name="connectionManager" ref="ky.pollingConnectionManager" /> <!--開啟重試--> <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="User-Agent"/> <constructor-arg value="Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.16 Safari/537.36"/> </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="ky.httpClient" factory-bean="ky.httpClientBuilder" factory-method="build" /> <bean id="ky.clientHttpRequestFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"> <constructor-arg ref="ky.httpClient"/> <!--連接超時時間,毫秒--> <property name="connectTimeout" value="5000"/> <!--讀寫超時時間,毫秒--> <property name="readTimeout" value="10000"/> </bean> <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> <constructor-arg ref="ky.clientHttpRequestFactory"/> <property name="errorHandler"> <bean class="org.springframework.web.client.DefaultResponseErrorHandler"/> </property> <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>
bean初始化+靜態工具
線程安全的單例(懶漢模式)
基於jdk的spring的RestTemplate
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; /** * @title:基於jdk的spring的RestTemplate * @author:liuxing * @date:2015-05-18 09:35 */ @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; } }
使用Httpclient連接池的方式
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; /** * @title:使用spring的restTemplate替代httpclient工具 * @author:liuxing * @date:2015-05-18 08:48 */ public class RestClient { private static final Logger LOGGER = LoggerFactory.getLogger(SimpleRestClient.class); private static RestTemplate restTemplate; static { // 長連接保持30秒 PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS); // 總連接數 pollingConnectionManager.setMaxTotal(500); // 同路由的並發數 pollingConnectionManager.setDefaultMaxPerRoute(500); HttpClientBuilder httpClientBuilder = HttpClients.custom(); httpClientBuilder.setConnectionManager(pollingConnectionManager); // 重試次數,默認是3次,沒有開啟 httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(2, 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) 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,zh;q=0.8,en;q=0.6")); 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 StringHttpMessageConverter(Charset.forName("UTF-8"))); messageConverters.add(new FormHttpMessageConverter()); messageConverters.add(new MappingJackson2XmlHttpMessageConverter()); messageConverters.add(new MappingJackson2HttpMessageConverter()); messageConverters.add(new ByteArrayHttpMessageConverter()); restTemplate = new RestTemplate(messageConverters); restTemplate.setRequestFactory(clientHttpRequestFactory); restTemplate.setErrorHandler(new DefaultResponseErrorHandler()); LOGGER.info("RestClient初始化完成"); } private RestClient() { } public static RestTemplate getClient() { return restTemplate; } }
使用樣例
注意點
api里面可以做自動的參數匹配:
如:http://you domainn name/test?empNo={empNo},則下面方法的最后一個參數為數據匹配參數,會自動根據key進行查找,然后替換
API沒有聲明異常,注意進行異常處理
更多使用語法請查看API文檔
完整的實例代碼
定義一個異常
import org.springframework.core.NestedRuntimeException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; /** * 包裝一個RestClient請求時拋出的異常 * * @author :liuxing * @since :2015-07-15 21:33 */ public class RestClientException extends NestedRuntimeException { /** * 狀態碼 */ private HttpStatus statusCode; /** * 狀態碼文本 */ private String statusText; /** * 異常時返回的內容 */ private String responseBody; /** * 返回的頭 */ private HttpHeaders responseHeaders; public RestClientException(Exception exception) { super(exception.getMessage(), exception); if (exception instanceof HttpServerErrorException) { HttpServerErrorException e = (HttpServerErrorException) exception; this.statusCode = e.getStatusCode(); this.statusText = e.getStatusText(); this.responseBody = e.getResponseBodyAsString(); this.responseHeaders = e.getResponseHeaders(); } else if (exception instanceof HttpClientErrorException) { HttpClientErrorException e = (HttpClientErrorException) exception; this.statusCode = e.getStatusCode(); this.statusText = e.getStatusText(); this.responseBody = e.getResponseBodyAsString(); this.responseHeaders = e.getResponseHeaders(); } else { this.statusText = exception.getMessage(); } } public HttpStatus getStatusCode() { return statusCode; } public void setStatusCode(HttpStatus statusCode) { this.statusCode = statusCode; } public String getStatusText() { return statusText; } public void setStatusText(String statusText) { this.statusText = statusText; } public String getResponseBody() { return responseBody; } public void setResponseBody(String responseBody) { this.responseBody = responseBody; } public HttpHeaders getResponseHeaders() { return responseHeaders; } public void setResponseHeaders(HttpHeaders responseHeaders) { this.responseHeaders = responseHeaders; } }
工具集
import com.dooioo.se.commons.Lang; import com.dooioo.se.utils.RestClientBuilder; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.collections.MapUtils; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import java.lang.reflect.Field; import java.util.Collection; import java.util.HashMap; import java.util.Map; /** * httpclient工具類,基於httpclient 4.x * 不需要設置header的情況: * 1.普通的非校驗型請求 * 2.普通的表單請求 * <p/> * 需要設置header的情況: * 1.頭部帶token校驗的請求 * 2.提交json數據的請求 * * @author 劉興 * @version V1.0 * @since 2014-3-7 下午7:48:58 */ public class RestClient { /** * 執行請求 * * @param url 請求地址 * @param method 請求方式 * @param responseType 返回的數據類型 * @param uriVariables url自動匹配替換的參數,如url為api/{a}/{b},參數為["1","2"],則解析的url為api/1/2,使用Map參數時,遵循按key匹配 * @return 結果對象 * @throws RestClientException RestClient異常,包含狀態碼和非200的返回內容 */ public static <T> T exchange(String url, HttpMethod method, Class<T> responseType, Object... uriVariables) throws RestClientException { return exchange(url, method, null, null, responseType, uriVariables); } /** * 執行請求 * * @param url 請求地址 * @param method 請求方式 * @param headers 設置的頭信息 * @param responseType 返回的數據類型 * @param uriVariables url自動匹配替換的參數,如url為api/{a}/{b},參數為["1","2"],則解析的url為api/1/2,使用Map參數時,遵循按key匹配 * @return 結果對象 * @throws RestClientException RestClient異常,包含狀態碼和非200的返回內容 */ public static <T> T exchange(String url, HttpMethod method, HttpHeaders headers, Class<T> responseType, Object... uriVariables) throws RestClientException { return exchange(url, method, headers, null, responseType, uriVariables); } /** * 執行請求 * * @param url 請求地址 * @param method 請求方式 * @param body 要提交的數據 * @param responseType 返回數據類型 * 返回bean時指定Class * @param uriVariables url自動匹配替換的參數,如url為api/{a}/{b},參數為["1","2"],則解析的url為api/1/2,使用Map參數時,遵循按key匹配 * @return 結果對象 * @throws RestClientException RestClient異常,包含狀態碼和非200的返回內容 */ public static <T> T exchange(String url, HttpMethod method, Object body, Class<T> responseType, Object... uriVariables) throws RestClientException { return exchange(url, method, null, body, responseType, uriVariables); } /** * 執行請求 * * @param url 請求地址 * @param method 請求方式 * @param httpHeaders 請求頭 * @param body 要提交的數據 * @param responseType 返回數據類型 * 返回bean時指定Class * @param uriVariables url自動匹配替換的參數,如url為api/{a}/{b},參數為["1","2"],則解析的url為api/1/2,使用Map參數時,遵循按key匹配 * @return 結果對象 * @throws RestClientException RestClient異常,包含狀態碼和非200的返回內容 */ public static <T> T exchange(String url, HttpMethod method, HttpHeaders httpHeaders, Object body, Class<T> responseType, Object... uriVariables) throws RestClientException { try { HttpEntity<?> requestEntity = new HttpEntity(body, httpHeaders); requestEntity = convert(requestEntity); if (uriVariables.length == 1 && uriVariables[0] instanceof Map) { Map<String, ?> _uriVariables = (Map<String, ?>) uriVariables[0]; return getClient().exchange(url, method, requestEntity, responseType, _uriVariables).getBody(); } return getClient().exchange(url, method, requestEntity, responseType, uriVariables).getBody(); } catch (Exception e) { throw new RestClientException(e); } } /** * 執行請求 * * @param url 請求地址 * @param method 請求方式 * @param responseType 返回的數據類型,例:new ParameterizedTypeReference<List<Bean>>(){} * @param uriVariables url自動匹配替換的參數,如url為api/{a}/{b},參數為["1","2"],則解析的url為api/1/2,使用Map參數時,遵循按key匹配 * @return 結果對象 * @throws RestClientException RestClient異常,包含狀態碼和非200的返回內容 */ public static <T> T exchange(String url, HttpMethod method, ParameterizedTypeReference<T> responseType, Object... uriVariables) throws RestClientException { return exchange(url, method, null, null, responseType, uriVariables); } /** * 執行請求 * * @param url 請求地址 * @param method 請求方式 * @param headers 設置的頭信息 * @param responseType 返回的數據類型,例:new ParameterizedTypeReference<List<Bean>>(){} * @param uriVariables url自動匹配替換的參數,如url為api/{a}/{b},參數為["1","2"],則解析的url為api/1/2,使用Map參數時,遵循按key匹配 * @return 結果對象 * @throws RestClientException RestClient異常,包含狀態碼和非200的返回內容 */ public static <T> T exchange(String url, HttpMethod method, HttpHeaders headers, ParameterizedTypeReference<T> responseType, Object... uriVariables) throws RestClientException { return exchange(url, method, headers, null, responseType, uriVariables); } /** * 執行請求 * * @param url 請求地址 * @param method 請求方式 * @param body 要提交的數據 * @param responseType 返回數據類型,例:new ParameterizedTypeReference<List<Bean>>(){} * 返回bean時指定Class * @param uriVariables url自動匹配替換的參數,如url為api/{a}/{b},參數為["1","2"],則解析的url為api/1/2,使用Map參數時,遵循按key匹配 * @return 結果對象 * @throws RestClientException RestClient異常,包含狀態碼和非200的返回內容 */ public static <T> T exchange(String url, HttpMethod method, Object body, ParameterizedTypeReference<T> responseType, Object... uriVariables) throws RestClientException { return exchange(url, method, null, body, responseType, uriVariables); } /** * 執行請求 * * @param url 請求地址 * @param method 請求方式 * @param httpHeaders 請求頭 * @param body 要提交的數據 * @param responseType 返回數據類型,例:new ParameterizedTypeReference<List<Bean>>(){} * 返回bean時指定Class * @param uriVariables url自動匹配替換的參數,如url為api/{a}/{b},參數為["1","2"],則解析的url為api/1/2,使用Map參數時,遵循按key匹配 * @return 結果對象 * @throws RestClientException RestClient異常,包含狀態碼和非200的返回內容 */ public static <T> T exchange(String url, HttpMethod method, HttpHeaders httpHeaders, Object body, ParameterizedTypeReference<T> responseType, Object... uriVariables) throws RestClientException { try { HttpEntity<?> requestEntity = new HttpEntity(body, httpHeaders); requestEntity = convert(requestEntity); if (uriVariables.length == 1 && uriVariables[0] instanceof Map) { Map<String, ?> _uriVariables = (Map<String, ?>) uriVariables[0]; return getClient().exchange(url, method, requestEntity, responseType, _uriVariables).getBody(); } return getClient().exchange(url, method, requestEntity, responseType, uriVariables).getBody(); } catch (Exception e) { throw new RestClientException(e); } } /** * 獲得一個RestTemplate客戶端 * * @return */ public static RestTemplate getClient() { return RestClientBuilder.build(); } /** * 獲取一個application/x-www-form-urlencoded頭 * * @return */ public static HttpHeaders buildBasicFORMHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); return headers; } /** * 獲取一個application/json頭 * * @return */ public static HttpHeaders buildBasicJSONHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); return headers; } /** * 獲取一個text/html頭 * * @return */ public static HttpHeaders buildBasicHTMLHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.TEXT_HTML); return headers; } /** * 構建一個json頭 * * @param arrays * @return */ public static HttpHeaders buildJSONHeaders(Object... arrays) { if (arrays.length % 2 != 0) { throw new RuntimeException("arrays 長度 必須為偶數"); } HttpHeaders headers = buildBasicJSONHeaders(); for (int i = 0; i < arrays.length; i++) { headers.add(Lang.defaultEmptyStr(arrays[i]), Lang.defaultEmptyStr(arrays[++i])); } return headers; } /** * 對bean對象轉表單模型做處理 * * @param requestEntity * @return */ private static HttpEntity<?> convert(HttpEntity<?> requestEntity) { Object body = requestEntity.getBody(); HttpHeaders headers = requestEntity.getHeaders(); if (body == null) { return requestEntity; } if (body instanceof Map) { MultiValueMap<String, String> multiValueMap = new LinkedMultiValueMap<>(); Map<String, ?> _body = (Map<String, ?>) body; for (String key : _body.keySet()) { multiValueMap.add(key, MapUtils.getString(_body, key)); } requestEntity = new HttpEntity<>(multiValueMap, headers); } if (headers == null || !MediaType.APPLICATION_FORM_URLENCODED.equals(headers.getContentType())) { return requestEntity; } if (body instanceof String) { return requestEntity; } if (body instanceof Collection) { return requestEntity; } if (body instanceof Map) { return requestEntity; } MultiValueMap<String, Object> formEntity = new LinkedMultiValueMap<>(); Field[] fields = body.getClass().getDeclaredFields(); for (int i = 0; i < fields.length; i++) { String name = fields[i].getName(); String value = null; try { value = BeanUtils.getProperty(body, name); } catch (Exception e) { e.printStackTrace(); } formEntity.add(name, value); } return new HttpEntity<>(formEntity, headers); } public final static Object[] EMPTY_URI_VARIABLES = new Object[]{}; public final static HttpHeaders EMPTY_HEADERS = new HttpHeaders(); public final static Map<String, ?> EMPTY_BODY = new HashMap<>(1); public final static HttpEntity EMPTY_ENTITY = new HttpEntity(EMPTY_HEADERS); }
更多
RestTemplate API說明和使用參考
http://docs.spring.io/spring/docs/4.1.x/javadoc-api/org/springframework/web/client/RestTemplate.html
HttpClient官方示例和參數配置說明
http://hc.apache.org/httpcomponents-client-4.4.x/examples.html
http://hc.apache.org/httpcomponents-client-4.4.x/tutorial/html/index.html
依賴
spring 3.x以上
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.5.3</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.9.13</version> </dependency>
注意點
1.關於httpclient配置的defaultMaxPerRoute
和maxTotal
defaultMaxPerRoute
:最大路由並發數,以主機為單位maxTotal
:整個連接池的並發數
例如:defaultMaxPerRoute
為10,maxTotal
為100
假設只會訪問http://www.baidu.com和http://www.google.com
那么能同時並發到客源的只能是10,房源也是10,整個連接永遠不會到100
2.部分方法注意查看源碼,默認構造里面會新增常用的數據轉換器,spring對jackson比較情有獨鍾,在解析xml和json時,優先使用jackson
/** * Create a new instance of the {@link RestTemplate} using default settings. * Default {@link HttpMessageConverter}s are initialized. */ public RestTemplate() { this.messageConverters.add(new ByteArrayHttpMessageConverter()); this.messageConverters.add(new StringHttpMessageConverter()); this.messageConverters.add(new ResourceHttpMessageConverter()); this.messageConverters.add(new SourceHttpMessageConverter<Source>()); this.messageConverters.add(new AllEncompassingFormHttpMessageConverter()); if (romePresent) { this.messageConverters.add(new AtomFeedHttpMessageConverter()); this.messageConverters.add(new RssChannelHttpMessageConverter()); } if (jackson2XmlPresent) { messageConverters.add(new MappingJackson2XmlHttpMessageConverter()); } else if (jaxb2Present) { this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter()); } if (jackson2Present) { this.messageConverters.add(new MappingJackson2HttpMessageConverter()); } else if (gsonPresent) { this.messageConverters.add(new GsonHttpMessageConverter()); } } /** * Create a new instance of the {@link RestTemplate} based on the given {@link ClientHttpRequestFactory}. * @param requestFactory HTTP request factory to use * @see org.springframework.http.client.SimpleClientHttpRequestFactory * @see org.springframework.http.client.HttpComponentsClientHttpRequestFactory */ public RestTemplate(ClientHttpRequestFactory requestFactory) { this(); setRequestFactory(requestFactory); }
再看添加轉換器的方法外部添加轉換器時,this.messageConverters.clear();會先清除已有的,需要注意
/** * Create a new instance of the {@link RestTemplate} using the given list of * {@link HttpMessageConverter} to use * @param messageConverters the list of {@link HttpMessageConverter} to use * @since 3.2.7 */ public RestTemplate(List<HttpMessageConverter<?>> messageConverters) { Assert.notEmpty(messageConverters, "'messageConverters' must not be empty"); this.messageConverters.addAll(messageConverters); } /** * Set the message body converters to use. * <p>These converters are used to convert from and to HTTP requests and responses. */ public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) { Assert.notEmpty(messageConverters, "'messageConverters' must not be empty"); // Take getMessageConverters() List as-is when passed in here if (this.messageConverters != messageConverters) { this.messageConverters.clear(); this.messageConverters.addAll(messageConverters); } }
本文轉自:http://liuxing.info/2015/05/21/RestTemplate%E5%AE%9E%E8%B7%B5/#基於jdk的spring的RestTemplate