RestTemplete默認不是支持所有的contentType,需要自己配置RestTemplete,添加自定的請求轉換器,獲取對應的contentType的數據並進行轉換。
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate httpsRestTemplate(ClientHttpRequestFactory httpsFactory) {
RestTemplate restTemplate = new RestTemplate(httpsFactory);
// 添加自定義的轉換器
restTemplate.getMessageConverters().add(new CustomMappingJackson2HttpMessageConverter());
restTemplate.setErrorHandler(new ErrorResponseHandler());//自定義的錯誤處理,繼承DefaultResponseErrorHandler
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
interceptors.add(new RestClientInterceptor());//自定義攔截器,繼承於ClientHttpRequestInterceptor
restTemplate.setInterceptors(interceptors);
return restTemplate;
}
@Bean(name = "httpsFactory")
public HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory()
throws Exception {
CloseableHttpClient httpClient = HttpClientUtils.acceptsUntrustedCertsHttpClient();
HttpComponentsClientHttpRequestFactory httpsFactory =
new HttpComponentsClientHttpRequestFactory(httpClient);
httpsFactory.setReadTimeout(40000);
httpsFactory.setConnectTimeout(40000);
return httpsFactory;
}
}
自定義的消息轉換器
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* http消息轉換器
* 支持所有消息轉換
* </p>
*/
public class CustomMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
public CustomMappingJackson2HttpMessageConverter() {
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.ALL);
setSupportedMediaTypes(mediaTypes);
}
}
RestTemplete支持https接口配置工具類
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class HttpClientUtils {
public static CloseableHttpClient acceptsUntrustedCertsHttpClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
HttpClientBuilder b = HttpClientBuilder.create();
// setup a Trust Strategy that allows all certificates.
//
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
return true;
}
}).build();
b.setSSLContext(sslContext);
// don't check Hostnames, either.
// -- use SSLConnectionSocketFactory.getDefaultHostnameVerifier(), if you don't want to weaken
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
// here's the special part:
// -- need to create an SSL Socket Factory, to use our weakened "trust strategy";
// -- and create a Registry, to register it.
//
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslSocketFactory)
.build();
// now, we create connection-manager using our Registry.
// -- allows multi-threaded use
PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager( socketFactoryRegistry);
connMgr.setMaxTotal(200);
connMgr.setDefaultMaxPerRoute(100);
b.setConnectionManager( connMgr);
// finally, build the HttpClient;
// -- done!
CloseableHttpClient client = b.build();
return client;
}
}
配置的RestTemplete攔截器,添加默認的hearder,攔截統一添加token
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import java.io.IOException;
import java.net.URI;
/**
* 攔截所有的restTemplate請求:
*/
public class RestClientInterceptor implements ClientHttpRequestInterceptor {
private static final String HEAD_TOKEN="Token";
private static final String HEAD_TRACE_ID="trace_id";
private static final String HEAD_SPAN_ID="span_id";
private SecurityAuthenticator identityAuthenticator = AuthenticatorFactory.getAuthenticator();
private static final Logger logger = LoggerFactory.getLogger(RestClientInterceptor.class);
@Override
public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] body, ClientHttpRequestExecution execution) throws IOException {
RequestHolder.setRequest(httpRequest);
HttpHeaders httpHeaders = httpRequest.getHeaders();
//沒有Token,增加Token參數
if(!httpHeaders.containsKey(HEAD_TOKEN)){
httpHeaders.add(HEAD_TOKEN, identityAuthenticator.getIdentityToken(null));
}
//如果沒有設置contentType,則設置默認爲application/json
MediaType contentType = httpHeaders.getContentType();
if(contentType == null){
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
}
TraceContext tc = TraceLocalUtil.getTraceContext();
if(tc==null){
//記錄是否爲當前調用鏈的發起方
RequestHolder.setStartFlag(true);
TraceRecordGenerator.traceStart();
}
URI uri = httpRequest.getURI();
HttpMethod httpMethod = httpRequest.getMethod();
TraceRecordGenerator.clientSend("call->" + httpMethod.name() + ":" + uri.toString());
tc = TraceLocalUtil.getTraceContext();
if (tc != null) {
httpHeaders.set(HEAD_TRACE_ID, tc.getTraceId());
httpHeaders.set(HEAD_SPAN_ID,tc.getSpanId());
}
final ClientHttpResponse response;
try {
response = execution.execute(httpRequest, body);
}catch (Exception e){
TraceRecordGenerator.clientReceiveFailed(e.getMessage(), ServicePropertyUtil.getErrorcodeProfix()+DefaultErrorCode.ERROR.getCode());
Boolean startFlag = RequestHolder.getStartFlag();
if(startFlag != null && startFlag){
TraceRecordGenerator.traceEnd();
}
RequestHolder.clear();
throw e;
}
return response;
}
}
部分代碼不方便給出,需要自行理解修改。