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
* RestTemplate會默認添加HttpMessageConverter,
* 而添加的StringHttpMessageConverter默認使用的字符集是ISO-8859-1,
* 在遇到中文的時候會有亂碼,所以需要移除原有的StringHttpMessageConverter,修改字符集爲UTF-8後重新設置。
*/
private void reInitMessageConverter(RestTemplate restTemplate) {
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
Iterator<HttpMessageConverter<?>> iterator = messageConverters.iterator();
while (iterator.hasNext()) {
HttpMessageConverter<?> converter = iterator.next();
if (converter instanceof StringHttpMessageConverter) {
((StringHttpMessageConverter) converter).setDefaultCharset(StandardCharsets.UTF_8);
}
}
}
/**
* 初始化RestTemplate,並加入spring的Bean工廠,由spring統一管理
*/
@Bean
@ConditionalOnMissingBean({RestOperations.class, RestTemplate.class})
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);
}
}