如今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
這裏主要討論的是經過第二個構造方法來使用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; } }
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包。網絡