什么是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

http://docs.spring.io/spring/docs/4.1.x/javadoc-api/org/springframework/http/client/SimpleClientHttpRequestFactory.html

http://docs.spring.io/spring/docs/4.1.x/javadoc-api/org/springframework/http/client/HttpComponentsClientHttpRequestFactory.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配置的defaultMaxPerRoutemaxTotal
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

RestTemplate实践的更多相关文章

  1. Spring提供的用于访问Rest服务的客户端:RestTemplate实践

    什么是RestTemplate? RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效 ...

  2. RestTemplate实践(及遇到的问题)

    在微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使用HTTP客户端.我们可以使用JDK原生的URLConnection.Apache的Http Client.Netty的异步 ...

  3. Spring RestTemplate 小结

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

  4. 《深入实践Spring Boot》阅读笔记之二:分布式应用开发

    上篇文章总结了<深入实践Spring Boot>的第一部分,这篇文章介绍第二部分:分布式应用开发,以及怎么构建一个高性能的服务平台. 主要从以下几个方面总结: Spring Boot SS ...

  5. Spring Cloud实践:降级、限流、滚动、灰度、AB、金丝雀的实现思路

    端口:8888,方便起见直接读取配置文件,生产环境可以读取git.application-dev.properties为全局配置.先启动配置中心,所有服务的配置(包括注册中心的地址)均从配置中心读取. ...

  6. 调用链监控 CAT 之 URL埋点实践

    URL监控埋点作用 一个http请求来了之后,会自动打点,能够记录每个url的访问情况,并将以此请求后续的调用链路串起来,可以在cat上查看logview 可以在cat Transaction及Eve ...

  7. 基于 Docker 的微服务架构实践

    本文来自作者 未闻 在 GitChat 分享的{基于 Docker 的微服务架构实践} 前言 基于 Docker 的容器技术是在2015年的时候开始接触的,两年多的时间,作为一名 Docker 的 D ...

  8. Springboot — 用更优雅的方式发HTTP请求(RestTemplate详解)

    RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率. 我之前的HTTP开发是用ap ...

  9. Spring Boot之发送HTTP请求(RestTemplate详解)

    原文作者:微笑面对生活 https://www.javazhiyin.com/19714.html#comment-345 RestTemplate是Spring提供的用于访问Rest服务的客户端,R ...

随机推荐

  1. angularjs实战

    1.指令  transclude 保留原来的内容 replace 去掉<my-directive>指令 <script src="http://apps.bdimg.com ...

  2. ServerSocket 默认邦定IP

    转自:http://cuisuqiang.iteye.com/blog/2037769 开发中需要开启服务端的时候,本地测试都是直接写端口,实际环境也是需要指定要邦定的IP才可以. 因为对于服务器来说 ...

  3. eclipse项目中关于导入的项目里提示HttpServletRequest 不能引用的解决办法

    eclipse项目中关于导入的项目里提示HttpServletRequest 不能引用的解决办法 当使用eclipse导入外部的web工程时,有时会提示HttpServletRequest, Serv ...

  4. 共享内存同行,王明学learn

    共享内存同行 一.共享内存概念 共享内存是IPC机制中的一种,它允许两个不相关的进程访问同一段内存, 这是传递数据的一种非常有效的方式. 二.函数学习 这里主要有创建共享内存.映射共享内存.分离共享内 ...

  5. ARM指令学习,王明学learn

    ARM指令学习 一.算数和逻辑指令 1— MOV 数据传送指令    2.— MVN 数据取反传送指令    3.— CMP 比较指令    4.— CMN 反值比较指令    5.— TST 位测试 ...

  6. poj 3264 【线段树】

    此题为入门级线段树 题意:给定Q(1<=Q<=200000)个数A1A2…AQ,多次求任一区间Ai-Aj中最大数和最小数的差 #include<algorithm> #incl ...

  7. Android中常用的五种数据存储方式

    第一种: 使用SharedPreferences存储数据 适用范围: 保存少量的数据,且这些数据的格式非常简单:字符串型.基本类型的值.比如应用程序的各种配置信息(如是否打开音效.是否使用震动效果.小 ...

  8. ERROR Shell: Failed to locate the winutils binary in the hadoop binary path

    文章发自:http://www.cnblogs.com/hark0623/p/4170172.html  转发请注明 14/12/17 19:18:53 ERROR Shell: Failed to ...

  9. 开发Portlet第三步:如何在Crystal Portlet中调用远程服务?

    当基于测试数据的Portlet调试完成后,接下来就是引入远程服务,替换测试数据. (此处以Dubbo框架远程服务为例) 分步指南 删除测试数据依赖:在pom.xml文件中,删除对****-servic ...

  10. Android Studio导出Jar包并混淆

    在Android Studio中,自带反编译查看class文件,如果没有混淆的话,class文件跟java文件基本没有区别了,为了保护,还是混淆的好. 网上看了不少资料,都是直接下载proguard额 ...