在Java Spring里提供了通过RestTemplate
调用http 请求的方法,这里汇总了在RestTemplate
的基础上通过apache httpclient
控制http请求的方式。
示例代码
RequestFactoryBuilder.java
使用apache httpclient
来构建并控制http链接相关信息:
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.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeader; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
public class RequestFactoryBuilder { private static HttpComponentsClientHttpRequestFactory clientHttpRequestFactory;
static { PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS); pollingConnectionManager.setMaxTotal(500); pollingConnectionManager.setDefaultMaxPerRoute(500);
HttpClientBuilder httpClientBuilder = HttpClients.custom(); httpClientBuilder.setConnectionManager(pollingConnectionManager); httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(2, true)); httpClientBuilder.setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE);
List<Header> headers = new ArrayList<>(); headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 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();
clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); clientHttpRequestFactory.setConnectTimeout(5000); clientHttpRequestFactory.setReadTimeout(5000); clientHttpRequestFactory.setConnectionRequestTimeout(200); }
public static HttpComponentsClientHttpRequestFactory get() { return clientHttpRequestFactory; } }
|
WebClient.java
import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List;
import org.apache.log4j.Logger; import org.springframework.http.converter.ByteArrayHttpMessageConverter; 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.DefaultResponseErrorHandler; import org.springframework.web.client.RestTemplate;
public class WebClient {
private static final Logger LOGGER = Logger.getLogger(WebClient.class);
private static RestTemplate restTemplate;
static { List<HttpMessageConverter<?>> messageConverters = new ArrayList<>(); messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8"))); messageConverters.add(new MappingJackson2HttpMessageConverter()); messageConverters.add(new FormHttpMessageConverter()); messageConverters.add(new MappingJackson2XmlHttpMessageConverter()); messageConverters.add(new ByteArrayHttpMessageConverter());
restTemplate = new RestTemplate(messageConverters); restTemplate.setRequestFactory(RequestFactoryBuilder.get()); restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
LOGGER.info("WebClient初始化完成"); }
public static RestTemplate getClient() { return restTemplate; } }
|
注意这里定义的HttpMessageConverter
,可根据需要调整对应的HttpMessageConverter
以及其顺序。
以上面代码为例,实际产生的http request header
信息如下:
GET / HTTP/1.1
Accept: text/plain, application/json, application/xml, application/*+json, */*
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36
Accept-Encoding: gzip,deflate
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Connection: keep-alive
|
常用的HttpMessageConverter
下面是相关说明:
MessageConverter |
说明 |
StringHttpMessageConverter |
T为String,可读取所有媒体类型(/), 从请求和响应读取/编写字符串。 默认情况下,它支持媒体类型 text/* 并使用文本/无格式内容类型编写。 |
FormHttpMessageConverter |
从请求和响应读取/编写表单数据。默认情况下,它读取媒体类型 application/x-www-form-urlencoded 并将数据写入 MultiValueMap。 |
MarshallingHttpMessageConverter |
T为Object,可读取text/xml和application/xml媒体类型请求, 使用 Spring 的 marshaller/un-marshaller 读取/编写 XML 数据。它转换媒体类型为 application/xml 的数据。 |
MappingJacksonHttpMessageConverter |
T为Object,可读取application/json, 使用 Jackson 的 ObjectMapper 读取/编写 JSON 数据。它转换媒体类型为 application/json 的数据。 |
AtomFeedHttpMessageConverter |
使用 ROME 的 Feed API 读取/编写 ATOM 源。它转换媒体类型为 application/atom+xml 的数据。 |
RssChannelHttpMessageConverter |
使用 ROME 的 feed API 读取/编写 RSS 源。它转换媒体类型为 application/rss+xml 的数据。 |
MappingJackson2XmlHttpMessageConverter |
T为Object,可读取text/xml和application/xml媒体类型请求, 从请求和响应读取/编写XML。默认情况下, 它转换媒体类型为application/xml, text/xml, and application/*+xml的数据 |
ByteArrayHttpMessageConverter |
T为byte[]类型,可读取/, 读取/编写二进制流,默认情绪下支持所有媒体类型(*/*), 它转换媒体类型为application/octet-stream的数据 |
Jaxb2RootElementHttpMessageConverter |
通过JAXB2读写XML信息,将请求消息转换到标注XmlRootElement和XmlType注解的类中,T为Object,可读取text/xml和application/xml媒体类型请求,响应信息的媒体类型为text/xml或application/xml |
Spring是如何寻找最佳的HttpMessageConverter
- 首先获取注册的所有HttpMessageConverter集合
- 然后客户端的请求header中寻找客户端可接收的类型,比如 Accept application/json,application/xml等,组成一个集合
- 所有的HttpMessageConverter 都有canRead和canWrite方法 返回值都是boolean,看这个HttpMessageConverter是否支持当前请求的读与写,读对应@RequestBody注解, 写对应@ResponseBody注解
- 遍历HttpMessageConverter集合与前面获取可接受类型进行匹配,如果匹配直接使用当前第一个匹配的HttpMessageConverter,然后return(一般是通过Accept和返回值对象的类型进行匹配)
参考