HttpClient之基本使用

1.HttpClient簡介

       http協議能夠說是如今Internet上面最重要,使用最多的協議之一了,愈來愈多的java應用須要使用http協議來訪問網絡資源,特別是如今rest api的流行,HttpClient 是 Apache Jakarta Common 下的子項目,用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包,而且它支持 HTTP 協議最新的版本和建議。HttpClient 已經應用在不少的項目中,好比 Apache Jakarta 上很著名的另外兩個開源項目 Cactus 和 HTMLUnit 都使用了 HttpClient,不少的java的爬蟲也是經過HttpClient實現的,研究HttpClient對咱們來講是很是重要的。javascript

2.HttpClient不是瀏覽器     

        不少人以爲既然HttpClient是一個HTTP客戶端編程工具,不少人把他當作瀏覽器來理解,可是其實HttpClient不是瀏覽器,它是一個HTTP通訊庫,所以它只提供一個通用瀏覽器應用程序所指望的功能子集,最根本的區別是HttpClient中沒有用戶界面,瀏覽器須要一個渲染引擎來顯示頁面,並解釋用戶輸入,例如鼠標點擊顯示頁面上的某處,有一個佈局引擎,計算如何顯示HTML頁面,包括級聯樣式表和圖像。javascript解釋器運行嵌入HTML頁面或從HTML頁面引用的javascript代碼。來自用戶界面的事件被傳遞到javascript解釋器進行處理。除此以外,還有用於插件的接口,能夠處理Applet,嵌入式媒體對象(如pdf文件,Quicktime電影和Flash動畫)或ActiveX控件(能夠執行任何操做)。HttpClient只能以編程的方式經過其API用於傳輸和接受HTTP消息。HttpClient也是徹底內容不可知的。html

       另外一個主要區別是對錯誤輸入或HTTP標準違規的容忍。 須要容許無效的用戶輸入,以使瀏覽器用戶友好。 還須要對從服務器檢索的畸形文檔的容忍度,以及在執行協議時服務器行爲的缺陷,使盡量多的用戶可訪問的網站。 然而,HttpClient努力在默認狀況下儘量接近並遵照HTTP標準規範和相關標準。 它還提供了一些手段來放鬆規範所施加的一些限制,這些限制容許或要求與不兼容的HTTP源或代理服務器兼容。java

3.HttpClient入門使用

        注意這個版本主要是基於HttpClient4.5.2版本的來說解的,也是如今最新的版本,之因此要提供版本說明的是由於HttpClient 3版本和HttpClient 4版本差異仍是不少大的,基本HttpClient裏面的接口都變了,你把HttpClient 3版本的代碼拿到HttpClient 4上面都運行不起來,會報錯的。因此這兒必定要注意,好了廢話很少說了,開始。apache

3.1.在pom.xml加入對httpclient的必需的jar包的依賴

 //httpclient的接口基本都在這兒 
   <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpclient</artifactId>
      <version>4.5.2</version>
    </dependency>
    //httpclient緩存
    <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpclient-cache</artifactId>
      <version>4.5</version>
    </dependency>
    //http的mime類型都在這裏面
    <dependency>
     <groupId>org.apache.httpcomponents</groupId>
     <artifactId>httpmime</artifactId>
     <version>4.3.2</version>
    </dependency>

  

注意:常見的MIME類型(通用型):編程

    超文本標記語言文本 .html text/htmlapi

    xml文檔 .xml text/xml瀏覽器

    XHTML文檔 .xhtml application/xhtml+xml緩存

    普通文本 .txt text/plain服務器

    RTF文本 .rtf application/rtf網絡

    PDF文檔 .pdf application/pdf

    Microsoft Word文件 .word application/msword

    PNG圖像 .png image/png

    GIF圖形 .gif image/gif

    JPEG圖形 .jpeg,.jpg image/jpeg

    au聲音文件 .au audio/basic

    MIDI音樂文件 mid,.midi audio/midi,audio/x-midi

    RealAudio音樂文件 .ra, .ram audio/x-pn-realaudio

    MPEG文件 .mpg,.mpeg video/mpeg

    AVI文件 .avi video/x-msvideo

    GZIP文件 .gz application/x-gzip

    TAR文件 .tar application/x-tar

    任意的二進制數據 application/octet-stream

3.2.抓取網頁的內容並打印到控制檯的demo

先直接貼代碼:

package fangdd.HttpClientDemo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Locale;

import org.apache.http.HttpEntity;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class HttpGetNewSample {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String url="http://www.baidu.com";

      
        //1.使用默認的配置的httpclient
        CloseableHttpClient client = HttpClients.createDefault();
        //2.使用get方法
        HttpGet httpGet = new HttpGet(url);
        InputStream inputStream = null;
        CloseableHttpResponse response = null;

        try {
            //3.執行請求,獲取響應
            response = client.execute(httpGet);
               

            //看請求是否成功,這兒打印的是http狀態碼
            System.out.println(response.getStatusLine().getStatusCode());
            //4.獲取響應的實體內容,就是咱們所要抓取得網頁內容
            HttpEntity entity = response.getEntity();

            //5.將其打印到控制檯上面
            //方法一:使用EntityUtils
            if (entity != null) {
                System.out.println(EntityUtils.toString(entity, "utf-8"));
            }
            EntityUtils.consume(entity);
            
            //方法二  :使用inputStream
           /* if (entity != null) {
                inputStream = entity.getContent();

                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                String line = "";
                while ((line = bufferedReader.readLine()) != null) {
                    System.out.println(line);

                }
            }*/

        } catch (UnsupportedOperationException | IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        }

    }

}

  

3.3HttpClient編寫程序流程總結

其實從上面咱們就能夠總結出使用HttpClient其實分爲6個步驟

1.建立HttpClient對象

       這兒使用的是org.apache.http.impl.client.CloseableHttpClient,他是HttpClient接口的一個實例,建立該對象的最簡單方法是CloseableHttpClient client = HttpClients.createDefault();

HttpClients是建立CloseableHttpClient的工廠,採用默認的配置來建立實例,通常狀況下咱們就用這個默認的實例就足夠,後面咱們能夠去看下怎麼定製本身需求配置的來建立HttpClient接口的實例。若是你去看這個函數的源代碼,你能夠看到org.apache.http.client.CookieStore,org.apache.http.client.config.RequestConfig等等都是採用默認的。後面咱們會專門有篇博客探討怎麼根據本身的需求定製httpclient。

2.建立某種請求方法的實例

      建立某種請求的實例,並指定請求的url,若是是get請求,建立對象HttpGet,若是是post 請求,建立對象HttpPost。類型的還有 HttpHead, HttpPost, HttpPut, HttpDelete, HttpTrace, 還有 HttpOptions。分別對應HEAD、POST PUT、DELETE、TRACE、OPTIONS方法,每一個方法是作什麼的以下表:

方法 描述 是否包含主體
GET 從服務器獲取一份文檔
HEAD 只從服務器獲取文檔的首部
POST 向服務器發送須要處理的數據
PUT 將請求的主體部分存儲在服務器上
TRACE 對可能通過代理服務器傳送到服務器上去的報文進行追蹤
OPTIONS  決定能夠在服務器上執行哪些方法
DELETE 從服務器上刪除一份文檔

能夠看獲得在Http協議中,只有post方法和put方法的請求裏面有實體

3.若是有請求參數的話,Get方法直接寫在url後面,例如

HttpGet httpget = new HttpGet(
      「http://www.google.com/search?hl=zh-CN&q=httpclient&btnG=Google+Search&aq=f&oq=」);
 或者使用setParameter來設置參數

URI uri = new URIBuilder()
         .setScheme(「http」)
         .setHost(「www.google.com」)
         .setPath(「/ search」)
         .setParameter(「q」,「httpclient」)
         .setParameter(「btnG」,「Google搜索」)
         .setParameter(「aq」,「f」)
         .setParameter(「oq」,「」)
         。創建();
 HttpGet httpget = new HttpGet(uri);
 System.out.println(httpget.getURI());
stdout>

http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
post方法用setEntity(HttpEntity entity)方法來設置請求參數。

後面會詳細的探討Entity這個東西,這兒就不在贅敘。

  

4.發送請求。

       

 調用CloseableHttpClient對象的execute(HttpUriRequest request)發送請求,該方法返回一個CloseableHttpResponse對象。

 CloseableHttpResponse response = client.execute(post);,很明顯CloseableHttpResponse就是用了處理返回數據的實體,經過它咱們能夠拿到返回的狀態碼、首部、實體等等咱們須要的東西。

  

5.獲取請求結果。

        調用CloseableHttpResponse的getAllHeaders()、getHeaders(String name)等方法可獲取服務器的響應頭;調用CloseableHttpResponse的getEntity()方法可獲取HttpEntity對象,該對象包裝了服務器的響應內容。程序可經過該對象獲取服務器的響應內容。

 HttpEntity entity = response.getEntity();
            //5.將其打印到顯示器上面
             //方法一:使用EntityUtils
              /*
            if(entity!=null)
            {
                System.out.println(EntityUtils.toString(entity,"utf-8"));
            }
            
            EntityUtils.consume(entity)
            */
            //方法二  
            InputStream inputStream = entity.getContent();

            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String line = "";
            while ((line = bufferedReader.readLine()) != null) {
                System.out.println(line);

            }

  

經過CloseableHttpEntity的getEntity取得實體以後,有兩種處理結果的方法,

方法一:使用EntityUtils來處理。

       該類是官方提供的一個處理實體的工具類,toSting方法將返回的實體轉換爲字符串,可是官網不建議使用這個,除非響應實體從一個可信HTTP服務器發起和已知是有限長度的。

方法二:使用InputStream來讀取

       由於httpEntity.getContent方法返回的就是InputStream類型。這種方法是官網推薦的方式,須要記得的是要本身釋放底層資源。


6.關閉鏈接,釋放資源。

若是是使用EntityUtils來處理實體的使用    EntityUtils.consume(entity)來釋放資源,能夠看獲得該函數源碼爲:

public static void consume(final HttpEntity entity) throws IOException {
        if (entity == null) {
            return;
        }
        if (entity.isStreaming()) {
            final InputStream instream = entity.getContent();
            if (instream != null) {
                instream.close();
            }
        }
}

  

其實仍是經過關閉inputStream,而後最後咱們再關閉CloseableHttpResponse就能夠了

 

若是是使用InputStream來處理實體的,釋放代碼以下

CloseableHttpClient httpclient = HttpClients.createDefault();
 HttpGet httpget = new HttpGet(「http:// localhost /」);
 CloseableHttpResponse response = httpclient.execute(httpget);
try{
     HttpEntity entity = response.getEntity();
     if(entity!= null){
         InputStream instream = entity.getContent();
        try{
             //作一些有用的事情
         } finally {
             intream.close();
         }}
     }}
 } finally {
     response.close();
 }}

  

關閉內容流和關閉響應之間的區別是:前者將嘗試經過消耗實體內容來保持底層鏈接活動,然後者當即關閉並丟棄鏈接

相關文章
相關標籤/搜索