Restful接口配置自定義的RestTemplete

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;
    }
}

部分代碼不方便給出,需要自行理解修改。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章