在开发过程中,使用HTTP调用外系统必然不可避免,关于HTTP工具很多,我通常选用RestTemplate进行调用。调用方法可以分为两种:
1.直接在service中进行引用 ,这种方法会出现许多代码重复性工作,出现代码冗余。
@Autowired
private RestTemplate restTemplate;
2.进行封装成工具类。进行调用,这种方法将避免代码冗余,下面进行演示。
首先我们需要引用jar包
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
其次需要一个ErrorHandler
package com.example.demo.config;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.ResponseErrorHandler;
import java.io.IOException;
public class CustomResponseErrorHandler implements ResponseErrorHandler {
private ResponseErrorHandler responseErrorHandler = new DefaultResponseErrorHandler();
@Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
return responseErrorHandler.hasError(clientHttpResponse);
}
@Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
responseErrorHandler.handleError(clientHttpResponse);
}
}
然后进行RestTemplate配置,设置连接池
package com.example.demo.config;
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.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
import java.util.List;
@Configuration
public class RestTemplateConfig {
/**
* 连接池最大连接数
*/
private int maxTotalCount = 300;
/**
* 单个主机的最大连接数
*/
private int maxConnectPerRoute = 100;
/**
* 链接超时
*/
private int connectTimeOut = 30000;
/**
* 读取超时
*/
private int socketTimeOut = 30000;
/**
* 创建HTTP客户端工厂
* @param httpClient
* @return
*/
@Bean
public ClientHttpRequestFactory createFactory(HttpClient httpClient) {
return new HttpComponentsClientHttpRequestFactory(httpClient);
}
/**
* 初始化RestTemplate,并加入spring的bean工厂,交由spring统一管理
* @param creeateFactory
* @return
*/
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory creeateFactory) {
RestTemplate restTemplate = new RestTemplate(creeateFactory);
//工薪设置StringHttpMessageConverter字符集为UTF-8,解决中文乱码
List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();
HttpMessageConverter<?> converter = null;
for (HttpMessageConverter<?> item : converterList) {
if (StringHttpMessageConverter.class == item.getClass()) {
converter = item;
break;
}
}
if (null != converter) {
converterList.remove(converter);
}
converterList.add(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
restTemplate.setErrorHandler(new CustomResponseErrorHandler());
return restTemplate;
}
/**
* 创建HttpClient
* @return
*/
@Bean
public HttpClient httpClient() {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(this.maxTotalCount);
connectionManager.setDefaultMaxPerRoute(this.maxConnectPerRoute);
RequestConfig config = RequestConfig.custom()
.setSocketTimeout(this.socketTimeOut)
.setConnectTimeout(this.connectTimeOut)
.setConnectionRequestTimeout(this.connectTimeOut)
.build();
return HttpClientBuilder.create()
.setDefaultRequestConfig(config)
.setConnectionManager(connectionManager)
.build();
}
}
最后对RestTemplate进行封装,本文只进行post封装,如有其他需要,自行封装。
package com.example.demo.utils;
import com.alibaba.fastjson.JSONObject;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;
import org.thymeleaf.util.StringUtils;
public class RestTemplateConnection {
public static <T> ResponseEntity<T> postForEntity(String url, JSONObject requestParam, Class<T> responseType){
if(StringUtils.isEmpty(url)){
return null;
}
return exchange(url, HttpMethod.POST, requestParam, responseType);
}
private static <T> ResponseEntity<T> exchange(String url, HttpMethod httpMethod, JSONObject requestJson, Class<T> responseType){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> requestEntity = new HttpEntity<>(JSONObject.toJSONString(requestJson), headers);
ResponseEntity<T> responseEntity = null;
try{
//参考博主文章《获取properties或者yaml配置文件值》一文中,获取bean工具类
RestTemplate restTemplate = (RestTemplate)SpringApllicatonContext.getContext().getBean("restTemplate");
responseEntity = restTemplate.exchange(url, httpMethod, requestEntity, responseType);
if(!HttpStatus.OK.equals(responseEntity.getStatusCode())){
//自定义异常,交由统一异常管理
throw new Exception();
}
} catch (Exception e) {
e.printStackTrace();
}
return responseEntity;
}
}
注意:在封装过程中参考博主文章《获取properties或者yaml配置文件值》一文中,获取bean工具类
最后,演示
JSONObject object = new JSONObject();
object.put("id", "321");
ResponseEntity<String> responseEntity = RestTemplateConnection.postForEntity("127.0.0.1:8080/plum/v1/login", object, String.class);
String responseBody = responseEntity.getBody();