一、概述
在實際開發過程中,我們經常需要呼叫對方提供的介面或測試自己寫的介面是否合適。很多專案都會封裝規定好本身專案的介面規範,所以大多數需要去呼叫對方提供的介面或第三方介面(簡訊、天氣等)。
在Java專案中呼叫第三方介面的方式有:
透過JDK網路類
Java。net。HttpURLConnection
;
透過
common
封裝好的
HttpClient
;
透過Apache封裝好的
CloseableHttpClient
;
透過
SpringBoot-RestTemplate
;
二、 Java呼叫第三方http介面的方式
2。1、透過JDK網路類Java。net。HttpURLConnection
比較原始的一種呼叫做法,這裡把get請求和post請求都統一放在一個方法裡面。
實現過程:
GET:
建立遠端連線
設定連線方式(get、post、put。。。)
設定連線超時時間
設定響應讀取時間
發起請求
獲取請求資料
關閉連線
POST:
建立遠端連線
設定連線方式(get、post、put。。。)
設定連線超時時間
設定響應讀取時間
當向遠端伺服器傳送資料/寫資料時,需要設定為true(setDoOutput)
當前向遠端服務讀取資料時,設定為true,該引數可有可無(setDoInput)
設定傳入引數的格式:(setRequestProperty)
設定鑑權資訊:Authorization:(setRequestProperty)
設定引數
發起請求
獲取請求資料
關閉連線
直接上程式碼:
package com。riemann。springbootdemo。util。common。httpConnectionUtil; import org。springframework。lang。Nullable; import java。io。*;import java。net。HttpURLConnection;import java。net。MalformedURLException;import java。net。URL;import java。net。URLConnection; /** * @author riemann */public class HttpURLConnectionUtil { /** * Http get請求 * @param httpUrl 連線 * @return 響應資料 */ public static String doGet(String httpUrl){ //連結 HttpURLConnection connection = null; InputStream is = null; BufferedReader br = null; StringBuffer result = new StringBuffer(); try { //建立連線 URL url = new URL(httpUrl); connection = (HttpURLConnection) url。openConnection(); //設定請求方式 connection。setRequestMethod(“GET”); //設定連線超時時間 connection。setReadTimeout(15000); //開始連線 connection。connect(); //獲取響應資料 if (connection。getResponseCode() == 200) { //獲取返回的資料 is = connection。getInputStream(); if (null != is) { br = new BufferedReader(new InputStreamReader(is, “UTF-8”)); String temp = null; while (null != (temp = br。readLine())) { result。append(temp); } } } } catch (IOException e) { e。printStackTrace(); } finally { if (null != br) { try { br。close(); } catch (IOException e) { e。printStackTrace(); } } if (null != is) { try { is。close(); } catch (IOException e) { e。printStackTrace(); } } //關閉遠端連線 connection。disconnect(); } return result。toString(); } /** * Http post請求 * @param httpUrl 連線 * @param param 引數 * @return */ public static String doPost(String httpUrl, @Nullable String param) { StringBuffer result = new StringBuffer(); //連線 HttpURLConnection connection = null; OutputStream os = null; InputStream is = null; BufferedReader br = null; try { //建立連線物件 URL url = new URL(httpUrl); //建立連線 connection = (HttpURLConnection) url。openConnection(); //設定請求方法 connection。setRequestMethod(“POST”); //設定連線超時時間 connection。setConnectTimeout(15000); //設定讀取超時時間 connection。setReadTimeout(15000); //DoOutput設定是否向httpUrlConnection輸出,DoInput設定是否從httpUrlConnection讀入,此外發送post請求必須設定這兩個 //設定是否可讀取 connection。setDoOutput(true); connection。setDoInput(true); //設定通用的請求屬性 connection。setRequestProperty(“accept”, “*/*”); connection。setRequestProperty(“connection”, “Keep-Alive”); connection。setRequestProperty(“user-agent”, “Mozilla/4。0 (compatible; MSIE 6。0; Windows NT 5。1; SV1)”); connection。setRequestProperty(“Content-Type”, “application/json;charset=utf-8”); //拼裝引數 if (null != param && param。equals(“”)) { //設定引數 os = connection。getOutputStream(); //拼裝引數 os。write(param。getBytes(“UTF-8”)); } //設定許可權 //設定請求頭等 //開啟連線 //connection。connect(); //讀取響應 if (connection。getResponseCode() == 200) { is = connection。getInputStream(); if (null != is) { br = new BufferedReader(new InputStreamReader(is, “GBK”)); String temp = null; while (null != (temp = br。readLine())) { result。append(temp); result。append(“\r\n”); } } } } catch (MalformedURLException e) { e。printStackTrace(); } catch (IOException e) { e。printStackTrace(); } finally { //關閉連線 if(br!=null){ try { br。close(); } catch (IOException e) { e。printStackTrace(); } } if(os!=null){ try { os。close(); } catch (IOException e) { e。printStackTrace(); } } if(is!=null){ try { is。close(); } catch (IOException e) { e。printStackTrace(); } } //關閉連線 connection。disconnect(); } return result。toString(); } public static void main(String[] args) { String message = doPost(“https://tcc。taobao。com/cc/json/mobile_tel_segment。htm?tel=13026194071”, “”); System。out。println(message); }}
執行結果:
2。2 透過apache common封裝好的HttpClient
httpClient的get或post請求方式步驟:
生成一個HttpClient物件並設定相應的引數;
生成一個GetMethod物件或PostMethod並設定響應的引數;
用HttpClient生成的物件來執行GetMethod生成的Get方法;
處理響應狀態碼;
若響應正常,處理HTTP響應內容;
釋放連線。
匯入如下jar包:
<!——HttpClient——>
程式碼如下:
package com。riemann。springbootdemo。util。common。httpConnectionUtil; import com。alibaba。fastjson。JSONObject;import org。apache。commons。httpclient。*;import org。apache。commons。httpclient。methods。GetMethod;import org。apache。commons。httpclient。methods。PostMethod;import org。apache。commons。httpclient。params。HttpMethodParams; import java。io。IOException; /** * @author riemann */public class HttpClientUtil { /** * httpClient的get請求方式 * 使用GetMethod來訪問一個URL對應的網頁實現步驟: * 1。生成一個HttpClient物件並設定相應的引數; * 2。生成一個GetMethod物件並設定響應的引數; * 3。用HttpClient生成的物件來執行GetMethod生成的Get方法; * 4。處理響應狀態碼; * 5。若響應正常,處理HTTP響應內容; * 6。釋放連線。 * @param url * @param charset * @return */ public static String doGet(String url, String charset) { //1。生成HttpClient物件並設定引數 HttpClient httpClient = new HttpClient(); //設定Http連線超時為5秒 httpClient。getHttpConnectionManager()。getParams()。setConnectionTimeout(5000); //2。生成GetMethod物件並設定引數 GetMethod getMethod = new GetMethod(url); //設定get請求超時為5秒 getMethod。getParams()。setParameter(HttpMethodParams。SO_TIMEOUT, 5000); //設定請求重試處理,用的是預設的重試處理:請求三次 getMethod。getParams()。setParameter(HttpMethodParams。RETRY_HANDLER, new DefaultHttpMethodRetryHandler()); String response = “”; //3。執行HTTP GET 請求 try { int statusCode = httpClient。executeMethod(getMethod); //4。判斷訪問的狀態碼 if (statusCode != HttpStatus。SC_OK) { System。err。println(“請求出錯:” + getMethod。getStatusLine()); } //5。處理HTTP響應內容 //HTTP響應頭部資訊,這裡簡單列印 Header[] headers = getMethod。getResponseHeaders(); for(Header h : headers) { System。out。println(h。getName() + “————————-” + h。getValue()); } //讀取HTTP響應內容,這裡簡單列印網頁內容 //讀取為位元組陣列 byte[] responseBody = getMethod。getResponseBody(); response = new String(responseBody, charset); System。out。println(“——————-response:” + response); //讀取為InputStream,在網頁內容資料量大時候推薦使用 //InputStream response = getMethod。getResponseBodyAsStream(); } catch (HttpException e) { //發生致命的異常,可能是協議不對或者返回的內容有問題 System。out。println(“請檢查輸入的URL!”); e。printStackTrace(); } catch (IOException e) { //發生網路異常 System。out。println(“發生網路異常!”); } finally { //6。釋放連線 getMethod。releaseConnection(); } return response; } /** * post請求 * @param url * @param json * @return */ public static String doPost(String url, JSONObject json){ HttpClient httpClient = new HttpClient(); PostMethod postMethod = new PostMethod(url); postMethod。addRequestHeader(“accept”, “*/*”); postMethod。addRequestHeader(“connection”, “Keep-Alive”); //設定json格式傳送 postMethod。addRequestHeader(“Content-Type”, “application/json;charset=GBK”); //必須設定下面這個Header postMethod。addRequestHeader(“User-Agent”, “Mozilla/5。0 (Windows NT 10。0; Win64; x64) AppleWebKit/537。36 (KHTML, like Gecko) Chrome/58。0。3029。81 Safari/537。36”); //新增請求引數 postMethod。addParameter(“commentId”, json。getString(“commentId”)); String res = “”; try { int code = httpClient。executeMethod(postMethod); if (code == 200){ res = postMethod。getResponseBodyAsString(); System。out。println(res); } } catch (IOException e) { e。printStackTrace(); } return res; } public static void main(String[] args) { System。out。println(doGet(“http://tcc。taobao。com/cc/json/mobile_tel_segment。htm?tel=13026194071”, “GBK”)); System。out。println(“——————-分割線——————”); System。out。println(“——————-分割線——————”); System。out。println(“——————-分割線——————”); JSONObject jsonObject = new JSONObject(); jsonObject。put(“commentId”, “13026194071”); System。out。println(doPost(“http://tcc。taobao。com/cc/json/mobile_tel_segment。htm?tel=13026194071”, jsonObject)); }}
執行結果:
post請求的
jsonObject
的引數也成功寫入
2。3 透過Apache封裝好的CloseableHttpClient
CloseableHttpClient
是在
HttpClient
的基礎上修改更新而來的,這裡還涉及到請求頭token的設定(請求驗證),利用fastjson轉換請求或返回結果字串為json格式,當然上面兩種方式也是可以設定請求頭token、json的,這裡只在下面說明。
匯入如下jar包:
<!——CloseableHttpClient——>
程式碼如下:
package com。riemann。springbootdemo。util。common。httpConnectionUtil; import com。alibaba。fastjson。JSONObject;import org。apache。http。HttpResponse;import org。apache。http。HttpStatus;import org。apache。http。client。methods。CloseableHttpResponse;import org。apache。http。client。methods。HttpGet;import org。apache。http。client。methods。HttpPost;import org。apache。http。entity。StringEntity;import org。apache。http。impl。client。CloseableHttpClient;import org。apache。http。impl。client。HttpClientBuilder;import org。apache。http。util。EntityUtils; import java。io。IOException;import java。io。UnsupportedEncodingException; /** * @author riemann */public class CloseableHttpClientUtil { private static String tokenString = “”; private static String AUTH_TOKEN_EXPIRED = “AUTH_TOKEN_EXPIRED”; private static CloseableHttpClient httpClient = null; /** * 以get方式呼叫第三方介面 * @param url * @param token * @return */ public static String doGet(String url, String token) { //建立HttpClient物件 CloseableHttpClient httpClient = HttpClientBuilder。create()。build(); HttpGet httpGet = new HttpGet(url); if (null != tokenString && !tokenString。equals(“”)) { tokenString = getToken(); } //api_gateway_auth_token自定義header頭,用於token驗證使用 httpGet。addHeader(“api_gateway_auth_token”,tokenString); httpGet。addHeader(“User-Agent”, “Mozilla/5。0 (Windows NT 10。0; Win64; x64) AppleWebKit/537。36 (KHTML, like Gecko) Chrome/58。0。3029。81 Safari/537。36”); try { HttpResponse response = httpClient。execute(httpGet); if (response。getStatusLine()。getStatusCode() == HttpStatus。SC_OK) { //返回json格式 String res = EntityUtils。toString(response。getEntity()); return res; } } catch (IOException e) { e。printStackTrace(); } return null; } /** * 以post方式呼叫第三方介面 * @param url * @param json * @return */ public static String doPost(String url, JSONObject json) { if (null == httpClient) { httpClient = HttpClientBuilder。create()。build(); } HttpPost httpPost = new HttpPost(url); if (null != tokenString && tokenString。equals(“”)) { tokenString = getToken(); } //api_gateway_auth_token自定義header頭,用於token驗證使用 httpPost。addHeader(“api_gateway_auth_token”, tokenString); httpPost。addHeader(“User-Agent”, “Mozilla/5。0 (Windows NT 10。0; Win64; x64) AppleWebKit/537。36 (KHTML, like Gecko) Chrome/58。0。3029。81 Safari/537。36”); try { StringEntity se = new StringEntity(json。toString()); se。setContentEncoding(“UTF-8”); //傳送json資料需要設定contentType se。setContentType(“application/x-www-form-urlencoded”); //設定請求引數 httpPost。setEntity(se); HttpResponse response = httpClient。execute(httpPost); if (response。getStatusLine()。getStatusCode() == HttpStatus。SC_OK) { //返回json格式 String res = EntityUtils。toString(response。getEntity()); return res; } } catch (IOException e) { e。printStackTrace(); } finally { if (httpClient != null){ try { httpClient。close(); } catch (IOException e) { e。printStackTrace(); } } } return null; } /** * 獲取第三方介面的token */ public static String getToken() { String token = “”; JSONObject object = new JSONObject(); object。put(“appid”, “appid”); object。put(“secretkey”, “secretkey”); if (null == httpClient) { httpClient = HttpClientBuilder。create()。build(); } HttpPost httpPost = new HttpPost(“http://localhost/login”); httpPost。addHeader(“User-Agent”, “Mozilla/5。0 (Windows NT 10。0; Win64; x64) AppleWebKit/537。36 (KHTML, like Gecko) Chrome/58。0。3029。81 Safari/537。36”); try { StringEntity se = new StringEntity(object。toString()); se。setContentEncoding(“UTF-8”); //傳送json資料需要設定contentType se。setContentType(“application/x-www-form-urlencoded”); //設定請求引數 httpPost。setEntity(se); HttpResponse response = httpClient。execute(httpPost); //這裡可以把返回的結果按照自定義的返回資料結果,把string轉換成自定義類 //ResultTokenBO result = JSONObject。parseObject(response, ResultTokenBO。class); //把response轉為jsonObject JSONObject result = (JSONObject) JSONObject。parseObject(String。valueOf(response)); if (result。containsKey(“token”)) { token = result。getString(“token”); } } catch (IOException e) { e。printStackTrace(); } return token; } /** * 測試 */ public static void test(String telephone) { JSONObject object = new JSONObject(); object。put(“telephone”, telephone); //首先獲取token tokenString = getToken(); String response = doPost(“http://localhost/searchUrl”, object); //如果返回的結果是list形式的,需要使用JSONObject。parseArray轉換 //List
2。4 透過SpringBoot-RestTemplate
springBoot-RestTemple
是上面三種方式的集大成者,程式碼編寫更加簡單,目前可以採用的呼叫第三方介面有:
delete()
在特定的URL上對資源執行
HTTP DELETE
操作
exchange()
在URL上執行特定的HTTP方法,返回包含物件的
ResponseEntity
,這個物件是從響應體中對映得到的
execute()
在URL上執行特定的HTTP方法,返回一個從響應體對映得到的物件
getForEntity()
傳送一個
HTTP GET
請求,返回的
ResponseEntity
包含了響應體所對映成的物件
getForObject()
傳送一個
HTTP GET
請求,返回的請求體將對映為一個物件
postForEntity()
POST 資料到一個URL,返回包含一個物件的
ResponseEntity
,這個物件是從響應體中對映得到的
postForObject()
POST 資料到一個URL,返回根據響應體匹配形成的物件
headForHeaders()
傳送
HTTP HEAD
請求,返回包含特定資源URL的HTTP頭
optionsForAllow()
傳送
HTTP OPTIONS
請求,返回對特定URL的Allow頭資訊
postForLocation()
POST 資料到一個URL,返回新建立資源的URL
put()
PUT 資源到特定的URL
首先匯入springboot的web包
在啟動類同包下建立
RestTemplateConfig。java
類
import org。springframework。context。annotation。Bean;import org。springframework。context。annotation。Configuration;import org。springframework。http。client。ClientHttpRequestFactory;import org。springframework。http。client。SimpleClientHttpRequestFactory;import org。springframework。web。client。RestTemplate; /** * @author riemann */@Configurationpublic class RestTemplateConfig { @Bean public RestTemplate restTemplate(ClientHttpRequestFactory factory){ return new RestTemplate(factory); } @Bean public ClientHttpRequestFactory simpleClientHttpRequestFactory(){ SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); factory。setConnectTimeout(15000); factory。setReadTimeout(5000); return factory; }}
然後在Service類(
RestTemplateToInterface
)中注入使用
具體程式碼如下:
import com。alibaba。fastjson。JSONObject;import com。swordfall。model。User;import org。springframework。beans。factory。annotation。Autowired;import org。springframework。http。*;import org。springframework。stereotype。Service;import org。springframework。web。client。RestTemplate; /** * @author riemann */@Servicepublic class RestTemplateToInterface { @Autowired private RestTemplate restTemplate; /** * 以get方式請求第三方http介面 getForEntity * @param url * @return */ public User doGetWith1(String url){ ResponseEntity
2。5 透過okhttp
應大家的響應,okhttp 現在也是蠻流行的,基於手機端很火,這裡分享一下
OkHttpClient
客戶端,業務程式碼get、post請求直接呼叫就好哈。
pom檔案引入依賴包
@Slf4jpublic class OkHttpClient { private static final MediaType JSON = MediaType。parse(“application/json; charset=utf-8”); private volatile static okhttp3。OkHttpClient client; private static final int MAX_IDLE_CONNECTION = Integer 。parseInt(ConfigManager。get(“httpclient。max_idle_connection”)); private static final long KEEP_ALIVE_DURATION = Long 。parseLong(ConfigManager。get(“httpclient。keep_alive_duration”)); private static final long CONNECT_TIMEOUT = Long。parseLong(ConfigManager。get(“httpclient。connectTimeout”)); private static final long READ_TIMEOUT = Long。parseLong(ConfigManager。get(“httpclient。 ”)); /** * 單例模式(雙重檢查模式) 獲取類例項 * * @return client */ private static okhttp3。OkHttpClient getInstance() { if (client == null) { synchronized (okhttp3。OkHttpClient。class) { if (client == null) { client = new okhttp3。OkHttpClient。Builder() 。connectTimeout(CONNECT_TIMEOUT, TimeUnit。SECONDS) 。readTimeout(READ_TIMEOUT, TimeUnit。SECONDS) 。connectionPool(new ConnectionPool(MAX_IDLE_CONNECTION, KEEP_ALIVE_DURATION, TimeUnit。MINUTES)) 。build(); } } } return client; } public static String syncPost(String url, String json) throws IOException { RequestBody body = RequestBody。create(JSON, json); Request request = new Request。Builder() 。url(url) 。post(body) 。build(); try { Response response = OkHttpClient。getInstance()。newCall(request)。execute(); if (response。isSuccessful()) { String result = response。body()。string(); log。info(“syncPost response = {}, responseBody= {}”, response, result); return result; } String result = response。body()。string(); log。info(“syncPost response = {}, responseBody= {}”, response, result); throw new IOException(“三方介面返回http狀態碼為” + response。code()); } catch (Exception e) { log。error(“syncPost() url:{} have a ecxeption {}”, url, e); throw new RuntimeException(“syncPost() have a ecxeption {}” + e。getMessage()); } } public static String syncGet(String url, Map