Java實現呼叫HTTP請求的幾種常見方式

一、概述

在實際開發過程中,我們經常需要呼叫對方提供的介面或測試自己寫的介面是否合適。很多專案都會封裝規定好本身專案的介面規範,所以大多數需要去呼叫對方提供的介面或第三方介面(簡訊、天氣等)。

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

執行結果:

Java實現呼叫HTTP請求的幾種常見方式

2。2 透過apache common封裝好的HttpClient

httpClient的get或post請求方式步驟:

生成一個HttpClient物件並設定相應的引數;

生成一個GetMethod物件或PostMethod並設定響應的引數;

用HttpClient生成的物件來執行GetMethod生成的Get方法;

處理響應狀態碼;

若響應正常,處理HTTP響應內容;

釋放連線。

匯入如下jar包:

<!——HttpClient——> commons-httpclient commons-httpclient 3。1 <!——fastjson——> com。alibaba fastjson 1。2。32

程式碼如下:

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

執行結果:

Java實現呼叫HTTP請求的幾種常見方式

post請求的

jsonObject

的引數也成功寫入

2。3 透過Apache封裝好的CloseableHttpClient

CloseableHttpClient

是在

HttpClient

的基礎上修改更新而來的,這裡還涉及到請求頭token的設定(請求驗證),利用fastjson轉換請求或返回結果字串為json格式,當然上面兩種方式也是可以設定請求頭token、json的,這裡只在下面說明。

匯入如下jar包:

<!——CloseableHttpClient——> org。apache。httpcomponents httpclient 4。5。2 <!——fastjson——> com。alibaba fastjson 1。2。32

程式碼如下:

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 list = JSONObject。parseArray(response, Result。class); System。out。println(response); } public static void main(String[] args) { test(“12345678910”); }}

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包

org。springframework。boot spring-boot-starter-parent 2。0。4。RELEASE <!——CloseableHttpClient——> org。apache。httpcomponents httpclient 4。5。2 <!——spring restTemplate——> <!—— @ConfigurationProperties annotation processing (metadata for IDEs) 生成spring-configuration-metadata。json類,需要引入此類——> org。springframework。boot spring-boot-configuration-processor true org。springframework。boot spring-boot-starter-aop org。springframework。boot spring-boot-starter-web org。springframework。boot spring-boot-starter-tomcat org。springframework。boot spring-boot-starter-jetty org。springframework。boot spring-boot-starter-test test

在啟動類同包下建立

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 responseEntity = restTemplate。getForEntity(url, User。class); User user = responseEntity。getBody(); return user; } /** * 以get方式請求第三方http介面 getForObject * 返回值返回的是響應體,省去了我們再去getBody() * @param url * @return */ public User doGetWith2(String url){ User user = restTemplate。getForObject(url, User。class); return user; } /** * 以post方式請求第三方http介面 postForEntity * @param url * @return */ public String doPostWith1(String url){ User user = new User(“小白”, 20); ResponseEntity responseEntity = restTemplate。postForEntity(url, user, String。class); String body = responseEntity。getBody(); return body; } /** * 以post方式請求第三方http介面 postForEntity * @param url * @return */ public String doPostWith2(String url){ User user = new User(“小白”, 20); String body = restTemplate。postForObject(url, user, String。class); return body; } /** * exchange * @return */ public String doExchange(String url, Integer age, String name){ //header引數 HttpHeaders headers = new HttpHeaders(); String token = “asdfaf2322”; headers。add(“authorization”, token); headers。setContentType(MediaType。APPLICATION_JSON); //放入body中的json引數 JSONObject obj = new JSONObject(); obj。put(“age”, age); obj。put(“name”, name); //組裝 HttpEntity request = new HttpEntity<>(obj, headers); ResponseEntity responseEntity = restTemplate。exchange(url, HttpMethod。POST, request, String。class); String body = responseEntity。getBody(); return body; }}

2。5 透過okhttp

應大家的響應,okhttp 現在也是蠻流行的,基於手機端很火,這裡分享一下

OkHttpClient

客戶端,業務程式碼get、post請求直接呼叫就好哈。

pom檔案引入依賴包

com。squareup。okhttp3 okhttp 3。10。0

@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 headParamsMap) throws IOException { Request request; final Request。Builder builder = new Request。Builder()。url(url); try { if (!CollectionUtils。isEmpty(headParamsMap)) { final Iterator> iterator = headParamsMap。entrySet() 。iterator(); while (iterator。hasNext()) { final Map。Entry entry = iterator。next(); builder。addHeader(entry。getKey(), (String) entry。getValue()); } } request = builder。build(); Response response = OkHttpClient。getInstance()。newCall(request)。execute(); String result = response。body()。string(); log。info(“syncGet response = {},responseBody= {}”, response, result); if (!response。isSuccessful()) { throw new IOException(“三方介面返回http狀態碼為” + response。code()); } return result; } catch (Exception e) { log。error(“remote interface url:{} have a ecxeption {}”, url, e); throw new RuntimeException(“三方介面返回異常”); } } }