1. 程式人生 > 其它 >JAVA實現HTTP請求 之 HTTPClient詳解

JAVA實現HTTP請求 之 HTTPClient詳解

技術標籤:Javahttpclienthttpjava實現httpjava

目錄

一、目前JAVA實現HTTP請求的方法用的最多的有兩種:

本篇介紹HTTPClient的使用.

二、依賴

三、HttpClient 之 URIBuilder

建構函式

URIBuilder類中方法:

四、HttpClient之基本使用步驟:

五、HttpClient之基本get用法

六、HttpClient之post - json用法

七、HttpClient之post - form用法

八、寫的比較好的, 關於HttpClient 的 blogs:


一、目前JAVA實現HTTP請求的方法用的最多的有兩種:

  1. 通過HTTPClient這種第三方開源框架去實現。HTTPClient對HTTP的封裝性比較不錯,基本上能夠滿足我們大部分的需求,最新的HttpClient4.5是org.apache.http.impl.client下操作遠端 url的工具包;HttpClient3.1 是 org.apache.commons.httpclient下操作遠端 url的工具包,雖然已不再更新,但實現工作中使用httpClient3.1的程式碼還是有不少的.
  2. 另一種則是通過HttpURLConnection去實現,HttpURLConnection是JAVA的標準類,是JAVA比較原生的一種實現方式。不要用這個了,有現成的工具為什麼不用呢.

本篇介紹HTTPClient的使用.

二、依賴

使用httpclient之前,先引入maven依賴:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.9</version>
</dependency>

三、HttpClient 之 URIBuilder

建構函式

  1. URIBuilder()
  2. URIBuilder(final String string) 內部會建立URI物件: digestURI(new URI(string))
  3. URIBuilder(final URI uri)

非空的兩個構造實際內部都呼叫了digestURI(uri) 將URI物件解析並賦值給類的屬性.

URIBuilder類中方法:

① get相關方法

    String url = "http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=";
    URIBuilder uriBuilder = new URIBuilder(url);
    System.out.println(uriBuilder.getScheme());
    System.out.println(uriBuilder.getUserInfo());
    System.out.println(uriBuilder.getHost());
    System.out.println(uriBuilder.getPort());
    System.out.println(uriBuilder.getPath());
    System.out.println(uriBuilder.getQueryParams());
    System.out.println(uriBuilder.getFragment());
    System.out.println(uriBuilder.getCharset());

    輸出如下所示:
    scheme:http
    userinfo:null
    host:www.google.com
    port:-1  埠預設是80,當顯示指定埠時,此處便能取到值
    path:/search
    queryParams:[hl=en, q=httpclient, btnG=Google Search, aq=f, oq=]
    fragment:null
    charset:null
    
    某些屬性含義未知手動設定一次
    String url = "http://info.sporttery.cn/football/info/fb_match_hhad.php?m=102909";
    URIBuilder uriBuilder = new URIBuilder(url);
    uriBuilder.setFragment("111");
    uriBuilder.setUserInfo("222", "333");
    uriBuilder.setCharset(new GBK());
    System.out.println(uriBuilder.build());
    System.out.println(uriBuilder.getScheme());
    System.out.println(uriBuilder.getUserInfo());
    System.out.println(uriBuilder.getHost());
    System.out.println(uriBuilder.getPath());
    System.out.println(uriBuilder.getQueryParams());
    System.out.println(uriBuilder.getFragment());
    System.out.println(uriBuilder.getCharset());
    輸出如下:
    http://222:[email protected]/football/info/fb_match_hhad.php?m=102909#111
    scheme:http
    userInfo:222:333   沒見過這東西-。-
    host:info.sporttery.cn
    path:/football/info/fb_match_hhad.php
    queryParams:[m=102909]
    fragment:111   路由
    charset:GBK

② 新增URI query引數方法

常用方法

  • setParameters(final List nvps)
  • setParameters(final NameValuePair… nvps)
  • addParameters(final List nvps)

上面的方法我覺得倆set其實是一樣的, set會覆蓋原來的同名引數而add不會

這裡的NameValuePair :

只有一個實現類BasicNameValuePair就是用來設定引數鍵值對BasicNameValuePair(final String name, final String value)

String url = "http://ads-mediation.internal.zkq.sg/media/app?m=102909";
    
URIBuilder uriBuilder = new URIBuilder(url);
ArrayList<NameValuePair> objects = new ArrayList<>();
NameValuePair m = new BasicNameValuePair("m", "1");
objects.add(m);
ArrayList<NameValuePair> objects1 = new ArrayList<>();
NameValuePair m1 = new BasicNameValuePair("m", "8");
objects1.add(m1);

uriBuilder.setParameters(objects);
uriBuilder.addParameters(objects1);
System.out.println(uriBuilder.build());
輸出:http://ads-mediation.internal.zkq.sg/media/app?m=1&m=8

得出結論:set會覆蓋原來的同名引數而add不會

  • addParameter(final String param, final String value)
  • setParameter(final String param, final String value)

param和value會在這倆個方法內部組裝成BasicNameValuePair.

String url = "hhttp://ads-mediation.internal.zkq.sg/media/app?m=102909";
URIBuilder uriBuilder = new URIBuilder(url);
uriBuilder.setParameter("m", "2");
uriBuilder.addParameter("m" ,"5");
System.out.println(uriBuilder.build());
輸出:http://ads-mediation.internal.zkq.sg/media/app?m=2&m=5
    
得出結論:set會覆蓋原來的同名引數而add不會

③Clears URI query parameters.

  • clearParameters() 清除所有引數 (即?後的鍵值對)
String url = "http://ads-mediation.internal.zkq.sg/media/app?m=102909";
URIBuilder uriBuilder = new URIBuilder(url);
uriBuilder.clearParameters();
System.out.println(uriBuilder.build());
輸出:http://ads-mediation.internal.zkq.sg/media/app

四、HttpClient之基本使用步驟:

使用HttpClient傳送請求、接收響應很簡單,一般需要如下幾步即可。

1. 建立HttpClient物件。

2. 建立請求方法的例項,並指定請求URL。如果需要傳送GET請求,建立HttpGet物件;如果需要傳送POST請求,建立HttpPost物件。

3. 如果需要傳送請求引數,可呼叫HttpGet、HttpPost共同的setParams(HetpParams params)方法來新增請求引數;對於HttpPost物件而言,也可呼叫setEntity(HttpEntity entity)方法來設定請求引數。

4. 呼叫HttpClient物件的execute(HttpUriRequest request)傳送請求,該方法返回一個HttpResponse。

5. 呼叫HttpResponse的getAllHeaders()、getHeaders(String name)等方法可獲取伺服器的響應頭;呼叫HttpResponse的getEntity()方法可獲取HttpEntity物件,該物件包裝了伺服器的響應內容。程式可通過該物件獲取伺服器的響應內容。

6. 釋放連線。無論執行方法是否成功,都必須釋放連線

五、HttpClient之基本get用法

public class HttpClientDemo {
   public void getRequest(String url) throws URISyntaxException, IOException {
     //建立httpClient例項
     CloseableHttpClient client = HttpClients.createDefault();
     //建立一個uri物件
     URIBuilder uriBuilder = new URIBuilder(url);
     //塞入form引數
     uriBuilder.addParameter("account", "123");
     uriBuilder.addParameter("password", "123");
     //建立httpGet遠端連線例項,這裡傳入目標的網路地址
     HttpGet httpGet = new HttpGet(uriBuilder.build());
     // 設定請求頭資訊,鑑權(沒有可忽略)
     httpGet.setHeader("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0");
     // 設定配置請求引數(沒有可忽略)
     RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 連線主機服務超時時間
           .setConnectionRequestTimeout(35000)// 請求超時時間
           .setSocketTimeout(60000)// 資料讀取超時時間
           .build();
     // 為httpGet例項設定配置
     httpGet.setConfig(requestConfig);
     //執行請求
     CloseableHttpResponse response = client.execute(httpGet);
     //獲取Response狀態碼
      int statusCode = response.getStatusLine().getStatusCode();
      System.out.println(statusCode);
     //獲取響應實體, 響應內容
      HttpEntity entity = response.getEntity();
     //通過EntityUtils中的toString方法將結果轉換為字串
      String str = EntityUtils.toString(entity);
      System.out.println(str);
      response.close();
      client.close();
   }
}
(如果用try catch 記得關閉資源)

六、HttpClient之post - json用法

 public String postRequest(String url, Map<String, Object> paramMap) {
     HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
     // 建立httpPost遠端連線例項
     HttpPost post = new HttpPost(url);
     String result = "";
     try (CloseableHttpClient closeableHttpClient = httpClientBuilder.build()) {
        // HttpEntity entity = new StringEntity(jsonDataStr);
        // 修復 POST json 導致中文亂碼
        HttpEntity entity = new StringEntity(paramMap.toString(), "UTF-8");
        post.setEntity(entity);
        post.setHeader("Content-type", "application/json");
        HttpResponse resp = closeableHttpClient.execute(post);
        try {
           InputStream respIs = resp.getEntity().getContent();
           byte[] respBytes = IOUtils.toByteArray(respIs);
           result = new String(respBytes, Charset.forName("UTF-8"));
        } catch (Exception e) {
           e.printStackTrace();
        }
        return result;
     } catch (IOException e) {
         e.printStackTrace();
     }
     return result;
}

七、HttpClient之post - form用法

form的關鍵在於生成NameValuePair ,這個集合裡面放入form 表單的元素.

隨後使用 HttpPost 的 setEntity(new UrlEncodedFormEntity(nameValuePair, HTTP.UTF_8)) 方法塞入生成的form元素集合.

總得來說, 就是通過一個NameValuePair集合來存放待提交的引數,並將這個引數集合傳入到一個UrlEncodedFormEntity中,然後呼叫HttpPost的setEntity()方法將構建好的UrlEncodedFormEntity傳入. 程式碼如下:

List<NameValuePair>params=newArrayList<NameValuePair>();

Params.add(new BasicNameValuePair(“username”,”admin”));

Params.add(new BasicNameValuePair(“password”,”123456”));

UrlEncodedFormEntity entity=newUrlEncodedFormEntity(params,”utf-8”);

httpPost.setEntity(entity);

示例程式碼如下 :

public static String postformRequest(String url, Map<String, Object> paramMap) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse httpResponse = null;
        String result = "";
        // 建立httpClient例項
        httpClient = HttpClients.createDefault();
        // 建立httpPost遠端連線例項
        HttpPost httpPost = new HttpPost(url);
        // 配置請求引數例項(不需要可忽略)
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 設定連線主機服務超時時間
                .setConnectionRequestTimeout(35000)// 設定連線請求超時時間
                .setSocketTimeout(60000)// 設定讀取資料連線超時時間
                .build();
        // 為httpPost例項設定配置(不需要可忽略)
        httpPost.setConfig(requestConfig);
        // 設定請求頭
        httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
        // 封裝表單引數
        if (null != paramMap && paramMap.size() > 0) {
            // 以下程式碼使用實現類BasicNameValuePair生成NameValuePair
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            // 通過map整合entrySet方法獲取entity
            Set<Entry<String, Object>> entrySet = paramMap.entrySet();
            // 迴圈遍歷,獲取迭代器
            Iterator<Entry<String, Object>> iterator = entrySet.iterator();
            while (iterator.hasNext()) {
                Entry<String, Object> mapEntry = iterator.next();
                nvps.add(new BasicNameValuePair(mapEntry.getKey(), mapEntry.getValue().toString()));
            }

            // 為httpPost設定封裝好的請求引數
            try {
                // post例項塞引數的方法
                httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        try {
            // 伺服器返回的所有資訊都在HttpResponse中, httpClient物件執行post請求,並返回響應引數物件
            httpResponse = httpClient.execute(httpPost);
            // 先取出伺服器返回的狀態碼,如果等於200說明success
            int code =httpResponse.getStatusLine().getStatusCode();
            // 從響應物件中獲取響應內容
            // EntityUtils.toString()有過載方法
            // 這個靜態方法將HttpEntity轉換成字串,防止伺服器返回的資料帶有中文,所以在轉換的時候將字符集指定成utf-8即可
            HttpEntity entity = httpResponse.getEntity();
            result = EntityUtils.toString(entity,"UTF-8");
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 關閉資源
            if (null != httpResponse) {
                try {
                    httpResponse.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != httpClient) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }
}

八、寫的比較好的, 關於HttpClient 的 blogs:

放2個連結在這 :

https://www.cnblogs.com/mufengforward/p/10510337.html https://www.cnblogs.com/xiayahui/p/5623947.html