使用HttpClient4來構建Spring RestTemplate

Spring RestTemplate簡單說明

如今REST服務已經很普及了,在咱們的程序中,常常會須要調用REST API,這時候會有不少選擇,原始一點的JDK自帶的,再進一步點使用HttpClient,或者說若是咱們使用Jersey這種框架的話,也會自帶rest client。可是咱們項目使用的SpringMVC,因此直接使用RestTemplate。使用RestTemplate比直接使用Httpclient簡單不少,同時也能夠藉助httpclient來實現RestTemplate。html

經過使用RestTemplate僅僅只須要寫幾行代碼,就能夠完成直接使用httpclient不少行代碼的事情,具體見:https://spring.io/blog/2009/03/27/rest-in-spring-3-resttemplatejava

RestTemplate有三個構造函數:web

  1. 默認構造函數,默認使用SimpleClientHttpRequestFactory,使用JDK自帶的java.net包進行網絡傳輸。
  2. public RestTemplate(ClientHttpRequestFactory requestFactory)。傳入一個ClientHttpRequestFactory,ClientHttpRequestFactory在Spring中的實現有不少個,如HttpComponentsClientHttpRequestFactory,Netty4ClientHttpRequestFactory等,具體的能夠看代碼,這裏只介紹HttpComponentsClientHttpRequestFactory,須要用到 HttpClient4.
  3. public RestTemplate(List<HttpMessageConverter<?>> messageConverters),使用SpringMvc的應該對HttpMessageConverter很熟悉了,RestTemplate默認會給咱們設置好經常使用的HttpMessageConverter,我通常不多使用到這個構造方法。

HttpComponentsClientHttpRequestFactory

這裏主要討論的是經過第二個構造方法來使用HttpClient4 來進行網絡傳輸。下面咱們來看下HttpComponentsClientHttpRequestFactory這個類。先看看他的構造方法spring

/**
     * Create a new instance of the {@code HttpComponentsClientHttpRequestFactory}
     * with a default {@link HttpClient}.
     */
    public HttpComponentsClientHttpRequestFactory() {
        this(HttpClients.createSystem());
    }

    /**
     * Create a new instance of the {@code HttpComponentsClientHttpRequestFactory}
     * with the given {@link HttpClient} instance.
     * <p>As of Spring Framework 4.0, the given client is expected to be of type
     * {@link CloseableHttpClient} (requiring HttpClient 4.3+).
     * @param httpClient the HttpClient instance to use for this request factory
     */
    public HttpComponentsClientHttpRequestFactory(HttpClient httpClient) {
        Assert.notNull(httpClient, "'httpClient' must not be null");
        Assert.isInstanceOf(CloseableHttpClient.class, httpClient, "'httpClient' is not of type CloseableHttpClient");
        this.httpClient = (CloseableHttpClient) httpClient;
    }

若是咱們不指定一個HttpClient的話,會默認幫咱們建立一個,若是咱們程序調用比較頻繁的話,爲了提升性能,會考慮使用PoolingHttpClientConnectionManager來構建HttpClient,這時候就會使用到第二個。如何使用PoolingHttpClientConnectionManager來建立HttpClient呢?能夠參考幾個文章:http://www.yeetrack.com/?p=782 以及我前面的一篇:http://www.cnblogs.com/hupengcool/p/4554525.html ,這裏就不具體講了,能夠網上搜索相關資料。
下面寫寫代碼來描述下怎麼經過HttpComponentsClientHttpRequestFactory來建立RestTemplate,爲了方便建立HttpClient的代碼我就直接使用我前面文章中的代碼:apache

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.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;

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;

/**
 * Created by Administrator on 2015/6/8.
 */
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() {
            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;
    }

}

建立並使用RestTemplate

CloseableHttpClient httpClient = HttpClientUtils.acceptsUntrustedCertsHttpClient();
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
        RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
        String result = restTemplate.getForObject("http://www.baidu.com",String.class);
        System.out.println(result);

那麼問題來了,咱們既然是使用Spring,那確定但願把他RestTemplate配置成Spring bean來使用,HttpClient是線程安全的,他能夠在程序中共享,建立一個成Spring bean恰好。下面是xml配置。安全

<bean id="httpClient" class="com.hupengcool.util.HttpClientUtils" factory-method="acceptsUntrustedCertsHttpClient"/>

    <bean id="clientHttpRequestFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
        <constructor-arg ref="httpClient"/>
    </bean>

    <bean id="restTemplate" class=" org.springframework.web.client.RestTemplate">
        <constructor-arg ref="clientHttpRequestFactory" />
    </bean>

開始使用Spring RestTemplate吧。。。。。
PS:項目中除了Spring相關jar包外。須要添加HttpClient4.5,jackson 2.x的jar包。網絡

相關文章
相關標籤/搜索