package org.suifeng.baseframework.api.rest;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
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.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.List;
@Configuration
@ConditionalOnClass(value = {RestTemplate.class, HttpClient.class})
public class RestConfiguration {
@Autowired
private HttpRequestProperties httpRequestProperties;
@Autowired
private RestResponseErrorHandler restResponseErrorHandler;
/**
* 实例化RestTemplate对象
*/
@Bean
public RestTemplate restTemplate(){
RestTemplate restTemplate = getRestTemplate();
// 添加自定义请求头拦截器
// restTemplate.setInterceptors(Collections.singletonList(headerRequestInterceptor));
// 捕捉自定义的restException
restTemplate.setErrorHandler(restResponseErrorHandler);
return restTemplate;
}
/**
* 创建HTTP客户端工厂
*/
private ClientHttpRequestFactory createFactory() {
if (httpRequestProperties.getMaxTotalConnect() <= 0) {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(httpRequestProperties.getConnectTimeout());
factory.setReadTimeout(httpRequestProperties.getReadTimeout());
return factory;
}
HttpClient httpClient = HttpClientBuilder.create().setMaxConnTotal(httpRequestProperties.getMaxTotalConnect())
.setMaxConnPerRoute(httpRequestProperties.getMaxConnectPerRoute()).build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
factory.setConnectTimeout(httpRequestProperties.getConnectTimeout());
factory.setReadTimeout(httpRequestProperties.getReadTimeout());
return factory;
}
/**
* 重新初始化MessageConverter
*/
private void reInitMessageConverter(RestTemplate restTemplate) {
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
Iterator<HttpMessageConverter<?>> iterator = messageConverters.iterator();
while (iterator.hasNext()) {
HttpMessageConverter<?> converter = iterator.next();
/*
* RestTemplate会默认添加HttpMessageConverter,
* 而添加的StringHttpMessageConverter默认使用的字符集是ISO-8859-1,
* 在遇到中文的时候会有乱码,所以需要移除原有的StringHttpMessageConverter,修改字符集为UTF-8后重新设置。
*/
if (converter instanceof StringHttpMessageConverter) {
((StringHttpMessageConverter) converter).setDefaultCharset(StandardCharsets.UTF_8);
}
/*
* 由于MessageConverter消息转换器机制会判断"com.fasterxml.jackson.dataformat.xml.XmlMapper"是否存在,
* 若存在则引入MappingJackson2XmlHttpMessageConverter,该消息转换器会优先于MappingJackson2HttpMessageConverter转换消息,
* 导致调用接口返回xml格式,故要将其移除(或者降低其优先级)以返回json
*/
if (converter instanceof MappingJackson2XmlHttpMessageConverter) {
iterator.remove();
}
}
}
/**
* 初始化RestTemplate,并加入spring的Bean工厂,由spring统一管理
*/
public RestTemplate getRestTemplate() {
RestTemplate restTemplate = new RestTemplate(this.createFactory());
reInitMessageConverter(restTemplate);
return restTemplate;
}
}
package org.suifeng.baseframework.api.rest;
import lombok.Getter;
import lombok.Setter;
import org.springframework.stereotype.Component;
@Setter
@Getter
@Component
public class HttpRequestProperties {
/**
* 连接池的最大连接数默认为0
*/
private int maxTotalConnect;
/**
* 单个主机的最大连接数
*/
private int maxConnectPerRoute;
/**
* 连接超时默认2s
*/
private int connectTimeout;
/**
* 读取超时默认30s
*/
private int readTimeout;
}
package org.suifeng.baseframework.api.rest;
import org.suifeng.baseframework.api.common.exception.RestException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.client.DefaultResponseErrorHandler;
import java.io.IOException;
@Slf4j
@Component
public class RestResponseErrorHandler extends DefaultResponseErrorHandler {
/**
* 重写handleError,抛出RestException
*/
@Override
public void handleError(ClientHttpResponse response) throws IOException {
HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode());
log.debug("rest call has error: {}", statusCode.toString());
// 获取服务端返回的异常信息,并抛出接口异常
// 此处代码仅供参考
String body = IOUtils.toString(response.getBody(),"UTF-8");
throw new RestException(statusCode,body);
}
}