SpringBoot自带的RestTemplate是没有使用连接池的,只是SimpleClientHttpRequestFactory实现了ClientHttpRequestFactory、AsyncClientHttpRequestFactory 2个工厂接口,因此每次调用接口都会创建连接和销毁连接,如果是高并发场景下会大大降低性能。因此,我们可以使用Apache的HttpClient连接池。
pom.xml
<!-- RestTemplate使用Apache的HttpComponentsClientHttpRequestFactory替换掉Spring SimpleClientHttpRequestFactory 以使用Apache HttpClient的连接池。 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
RestTemplate配置类
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
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.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(50);
connectionManager.setDefaultMaxPerRoute(20);
RequestConfig requestConfig = RequestConfig
.custom()
.setConnectionRequestTimeout(5000) // timeout to get connection from pool
.setSocketTimeout(5000) // standard connection timeout
.setConnectTimeout(5000) // standard connection timeout
.build();
HttpClient httpClient = HttpClientBuilder.create()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(requestConfig).build();
ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
RestTemplate restTemplate = new RestTemplate(requestFactory);
//设置请求字符串的编码格式为UTF-8,防止发送请求的字符串乱码。
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}
}
调用
@Autowired
private RestTemplate restTemplate;
@Autowired
private ObjectMapper objectMapper;
public Res getData(Dto dto) {
String url = "https://xxx.com/api/xxx";
//封装请求头参数.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Content-Type", "application/json;charset=utf-8");
headers.set("自定义请求头key","自定义请求头value");
//防止中文乱码(不一定有用,如果还是乱码就改成byte[]接收,再new String(data, StandardCharsets.UTF_8);转为对应的编码)
//restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
Res res = restTemplate.postForEntity(url, new HttpEntity<>(dto, headers), Res.class).getBody();
return res;
}
用Jackson ObjectMapper.writeValueAsString来解决中文乱码(推荐)
String url = "https://xxx.com/api/xxx";
//封装请求头参数.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
//headers.set("Content-Type", "application/json;charset=utf-8");
//headers.set("自定义请求头key","自定义请求头value");
//解决中文乱码
String dtoJsonString = objectMapper.writeValueAsString(dto);
String res = restTemplate.postForEntity(url, new HttpEntity<>(dtoJsonString, headers), String.class).getBody();
return res;
用byte数组接收转码来解决中文乱码
String url = "https://xxx.com/api/xxx";
//封装请求头参数.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
//headers.set("Content-Type", "application/json;charset=utf-8");
//headers.set("自定义请求头key","自定义请求头value");
//解决中文乱码
byte[] data = restTemplate.postForEntity(url, new HttpEntity<>(dto, headers), byte[].class).getBody();
String res = new String(data, StandardCharsets.UTF_8);
return res;