背景
近期,由於項目的要求需要在自己的webservice中調用遠程的WebAPI(Restful format)。自己的webservice程序是用Java編碼寫的,所以需要在其中實現一個Client來調用遠程的Restful接口。
選型
其實在自己的項目里面也有類似的調用,當時使用的是“JAXRSClientFactory”獲得靜態代理client。 由於這種方式需要依賴於遠程調用的webservice接口(需要引入別人的jar包)。這就造成了高耦合。因此不適用。
所以需要以一種低耦合的方式來實現。便有了選型的想法。
在網上搜索一番后,基本定型為兩種方式:
1.HttpClient
2.RestTemplate
接下來就分別列出兩種方式的實現代碼
HttpClient
import java.io.IOException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ResponseHandler; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.BasicResponseHandler; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HttpClientUtil { private static final Logger log = LoggerFactory.getLogger(HttpClientUtil.class); private CloseableHttpClient httpClient = HttpClients.createDefault(); public static String executePost(String url, String tdfBase64) throws Exception { String result = null; HttpPost httpPost = new HttpPost(url); httpPost.setEntity(new HttpEntity<String>(tdfBase64)); HttpResponse response = httpClient.execute(httpPost); if (response != null) { HttpEntity resEntity = response.getEntity(); if (resEntity != null) { result = EntityUtils.toString(resEntity, "utf-8"); } } return result; } } public static void main(String[] args) { // TODO Auto-generated method stub String url = "http://169.8.160.201:8080/xx/Webservice/Submit"; String base64Tdf = "MS4wMToxMzIdMS4wMjowMjAxHTEuMDM6MR8wMR4yHzAwHTEuMDQ6SVJRHTEuMDU6MjAxNjA1MDQdMS4wNjoxHTEuMDc6Q09HRU5UHTEuMDg6VEhBSUxBTkQdMS4wOTpTRVFVRU5DRU5PMTIzNB0xLjExOjE5LjY5HTEuMTI6MTkuNjkcMi4wMDE6MzEdMi4wMDI6MDAdMi4xNzY6MDA3MDA5HA=="; HttpClientUtil client = new HttpClientUtil(); String result=client.executePost(url, base64Tdf, ""); System.out.println(result); }
RestTemplate
package com.biolive.client; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpEntity; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; public class RestTemplateClient { private static final Logger log = LoggerFactory.getLogger(RestTemplateClient.class); private static final int connectTimeout= 5000; private static final int readTimeOut=5000; private RestTemplate restTemplate; public RestTemplateClient(){ SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setConnectTimeout(connectTimeout); requestFactory.setReadTimeout(readTimeOut); restTemplate = new RestTemplate(requestFactory); } public String executePost(String url, String base64Tdf){ String result = null; HttpEntity<String>request = new HttpEntity<String>(base64Tdf); try{ result=restTemplate.postForObject(url, request, String.class); }catch(RestClientException ex){ ex.printStackTrace(); log.info("call post interface error: " + ex.getMessage()); } return result; } public static void main(String[] args) { // TODO Auto-generated method stub String url = "http://169.8.160.201:8080/xx/Webservice/Submit"; String base64Tdf = "MS4wMToxMzIdMS4wMjowMjAxHTEuMDM6MR8wMR4yHzAwHTEuMDQ6SVJRHTEuMDU6MjAxNjA1MDQdMS4wNjoxHTEuMDc6Q09HRU5UHTEuMDg6VEhBSUxBTkQdMS4wOTpTRVFVRU5DRU5PMTIzNB0xLjExOjE5LjY5HTEuMTI6MTkuNjkcMi4wMDE6MzEdMi4wMDI6MDAdMi4xNzY6MDA3MDA5HA=="; RestTemplateClient client = new RestTemplateClient(); String result=client.executePost(url, base64Tdf); System.out.println(result); } }
總結
首先,用兩種方法都可以在只知道url和方法類型(GET/POST/PUT/UPDATE)的情況下完成任務,調用的方式也非常類似。
RestTemplate是Spring官方封裝和推薦的client, 它優化了一些底層操作,使得我們可以更簡單的使用。此外,也可以根據自己的需要和Spring進行結合以及配置。
附錄
RestTemplate的使用
RestTemplate有兩個構造方法,分別是:
public RestTemplate() { /** ...初始化過程 */ } public RestTemplate(ClientHttpRequestFactory requestFactory) { this(); setRequestFactory(requestFactory); }
其中,第二個構造方法中可以傳入ClientHttpRequestFactory參數,第一個進行默認初始化,因為我們經常需要對請求超時進行設置並能夠對超時進行后續處理,而第一個構造方法,我們無法控制超時時間,第二個構造中的ClientHttpRequestFactory接口的實現類中存在timeout屬性,因此選用第二個構造方法。
在spring配置文件中進行如下配置:
<!-- 配置RestTemplate -->
<!--Http client Factory-->
<bean id="httpClientFactory" class="org.springframework.http.client.SimpleClientHttpRequestFactory"> <property name="connectTimeout" value="${connectTimeout}"/> <property name="readTimeout" value="${readTimeout}"/> </bean> <!--RestTemplate--> <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> <constructor-arg ref="httpClientFactory"/> </bean>
當然也可以直接使用:
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setConnectTimeout(1000); requestFactory.setReadTimeout(1000); RestTemplate restTemplate = new RestTemplate(requestFactory);
注意:ClientHttpRequestFactory 接口有4個實現類,分別是:
- AbstractClientHttpRequestFactoryWrapper 用來裝配其他request factory的抽象類。
- CommonsClientHttpRequestFactory 允許用戶配置帶有認證和http連接池的httpclient,已廢棄,推薦用HttpComponentsClientHttpRequestFactory。
- HttpComponentsClientHttpRequestFactory 同2.
- SimpleClientHttpRequestFactory 接口的一個簡單實現,可配置proxy,connectTimeout,readTimeout等參數
參考
http://www.cnblogs.com/softidea/p/5977375.html
http://blog.csdn.net/zpf336/article/details/73480810