相關(guān)依賴
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
代碼
restTemplate配置類
D:\springbootdemo\src\main\java\cn\greenleaf\config\RestTemplateConfiguration.java
package cn.greenleaf.config;
import cn.greenleaf.common.RequestResponseLoggingInterceptor;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.boot.web.client.RestTemplateBuilder;
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.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* @Auther: Leon Liu
* @Date: 2020/04/04/11:42
* @Description:
**/
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
RestTemplate restTemplate = builder.build();
//使用HttpClient代替默認(rèn)的simpleClient
restTemplate.setRequestFactory(clientHttpRequestFactory());
// 使用 utf-8 編碼集的 converter 替換默認(rèn)的 converter(默認(rèn)的 StringHttpMessageConverter 的編碼集為"ISO-8859-1")
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
messageConverters.removeIf(converter -> converter instanceof StringHttpMessageConverter);
//messageConverters.removeIf(converter -> converter instanceof MappingJackson2HttpMessageConverter); //去掉json自動解析
messageConverters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
//設(shè)置攔截器
restTemplate.setInterceptors(Collections.singletonList(new RequestResponseLoggingInterceptor()));
return restTemplate;
}
@Bean
public ClientHttpRequestFactory clientHttpRequestFactory() {
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setHttpClient(httpClientBuilder().build());
clientHttpRequestFactory.setConnectTimeout(3000); // 連接超時粱玲,毫秒
clientHttpRequestFactory.setReadTimeout(10000); // 讀寫超時捅位,毫秒
clientHttpRequestFactory.setConnectionRequestTimeout(2000);
return clientHttpRequestFactory;
}
@Bean
public HttpClientBuilder httpClientBuilder() {
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
//設(shè)置HTTP連接管理器
httpClientBuilder.setConnectionManager(poolingConnectionManager());
return httpClientBuilder;
}
@Bean
public HttpClientConnectionManager poolingConnectionManager() {
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build();
PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager(registry);
poolingConnectionManager.setMaxTotal(1000); // 連接池最大連接數(shù)
poolingConnectionManager.setDefaultMaxPerRoute(100); // 每個主機(jī)的并發(fā)
//啟動監(jiān)控線程定時清除不活動的連接
Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(new IdleConnectionMonitorThread(poolingConnectionManager),
1000, 500, TimeUnit.MILLISECONDS);
return poolingConnectionManager;
}
public static class IdleConnectionMonitorThread extends Thread {
private final HttpClientConnectionManager connMgr;
private volatile boolean shutdown;
public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) {
super();
this.connMgr = connMgr;
}
@Override
public void run() {
synchronized (this) {
// 關(guān)閉失效的連接
connMgr.closeExpiredConnections();
// 可選的, 關(guān)閉5秒內(nèi)不活動的連接
connMgr.closeIdleConnections(5, TimeUnit.SECONDS);
// LoggerUtils.getLogger().debug("close idle connections");
}
}
}
}
日志攔截器
D:\springbootdemo\src\main\java\cn\greenleaf\common\RequestResponseLoggingInterceptor.java
package cn.greenleaf.common;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StreamUtils;
import java.io.IOException;
import java.nio.charset.Charset;
/**
* @Auther: Leon Liu
* @Date: 2020/04/04/12:23
* @Description:
**/
public class RequestResponseLoggingInterceptor implements ClientHttpRequestInterceptor {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException
{
logRequest(request, body);
ClientHttpResponse response = execution.execute(request, body);
logResponse(response);
//Add optional additional headers
response.getHeaders().add("headerName", "VALUE");
return response;
}
private void logRequest(HttpRequest request, byte[] body) throws IOException
{
if (log.isDebugEnabled())
{
log.debug("===========================request begin================================================");
log.debug("URI : {}", request.getURI());
log.debug("Method : {}", request.getMethod());
log.debug("Headers : {}", request.getHeaders());
log.debug("Request body: {}", new String(body, "UTF-8"));
log.debug("==========================request end================================================");
}
}
private void logResponse(ClientHttpResponse response) throws IOException
{
if (log.isDebugEnabled())
{
log.debug("============================response begin==========================================");
log.debug("Status code : {}", response.getStatusCode());
log.debug("Status text : {}", response.getStatusText());
log.debug("Headers : {}", response.getHeaders());
log.debug("Response body: {}", StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
log.debug("=======================response end=================================================");
}
}
}
測試
D:\springbootdemo\src\test\java\cn\greenleaf\config\RestTemplateConfigurationTest.java
package cn.greenleaf.config;
import cn.greenleaf.domain.Cp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
/**
* @Auther: Leon Liu
* @Date: 2020/04/04/13:09
* @Description:
**/
@SpringBootTest
@RunWith(SpringRunner.class)
public class RestTemplateConfigurationTest {
@Autowired
RestTemplate restTemplate;
@Test
public void testGet() {
restTemplate.getForObject("https://www.baidu.com", String.class);
}
@Test
public void testPost() {
Map map = new HashMap();
map.put("offset", "0");
map.put("page_size", "1");
map.put("sign", "6fc9c71e4c5f5bf763f560d32b37bf17b5e6cd9e962ddd581e81b");
Cp cp = restTemplate.postForObject("http://hybrid.xiaomi.com/test/audit_app_list/fetch/", null, Cp.class, map);
}
}