Apache真是偉大,為我們提供了HttpClient.jar,這個HttpClient是客戶端的http通信實現庫,這個類庫的作用是接受和發送http報文,引進這個類庫,我們對於http的操作會變得簡單一些,事不宜遲,趕快介紹。
在將這個HttpClient之前,我們必須弄清兩個概念:URL和URI
URI(Universal Resource Identify),通用資源標識符,而URL(Uniform Resource Locator),統一資源定位符,兩個有什么區別,其實就是范圍大小的問題,URI是包含URL的,URI由訪問資源的命名機制、存放資源的主機名、資源自身的路徑組成,而URL由協議、資源的主機IP地址、主機資源的具體地址組成,有他們兩個的組成我們可以清楚的看出,其實URL就是我們平時輸入瀏覽器的地址,如“http://www.hao123.com”,URL是URI的具體表現形式而已,URI是包含URL的。
下面正式學習HttpClient:
我講解的這個HttpClient版本是4.0以上的,如果要運行我的代碼的話就要引用4.0以上的jar包。
1.創建一個客戶端,使用HttpClient,用它來處理與http相關的操作,我們可以理解為創建一個瀏覽器那樣:
HttpClient httpClient = new DefaultHttpClient();
2.創建一個HttpGet類,相當於與在瀏覽器中打開一個URL,該類的構造接受一個String類型的參數,就是我們要輸入的URL了:
HttpGet httpGet = new HttpGet("http://www.hao123.com");
3.通過HttpClient的execute方法,參數為HttpGet類型的參數,相當於打進網址后回車,這個我們可以得到HttpResponse,這個是代表請求后對應的響應:
HttpResponse response = httpClient.execute(httpGet);
4.通過這個response我們可以拿到一個HttpEntity類的實體,這個實體里面有着Http報文的許多信息,當然包括我們想要的內容:
HttpEntity entity = response.getEntity();
5.通過entity這個實體,我們可以調用它的getContent方法,拿到的就是網頁的內容,但這個內容是InputStream,不過有了InputStearm,什么都好辦了:
InputStream instream = entity.getContent();
下面我們來看看一個完整的抓取www.hao123.com內容的實例:
@Test public void testGet() throws Exception { HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet("http://www.hao123.com"); HttpResponse response = httpClient.execute(httpGet); HttpEntity entity = response.getEntity(); if (entity != null) { InputStream instream = entity.getContent(); int l; byte[] tmp = new byte[2048]; while ((l = instream.read(tmp)) != -1) { System.out.println(new String(tmp, 0, l, "utf-8")); } } }
下面具體一點來介紹:
1.Http請求
HttpClient支持所有定義在Http/1.1版本中的的方法:get、post、head、put、delete、trace和options,對應每個方法都有一個類:HttpGet、HttpPost、HttpHead、HttpPut、HttpDelete、HttpTrace和HttpOptions
上面這些方法類中,除了可以有String參數的構造方法外,還有一個URI參數的構造方法,通過這個uri就發出請求,這個URI類其實我們jdk自帶的,但是Apache真是為我們着想,提供了URIUtils類幫助我們,有興趣可以去了解一下。
2.Http響應
HttpResponse是HttpClient提供給我們的響應類,響應是服務器發給客戶端的報文,報文中包含了各種信息,通過下列方法我們可以拿到這些信息:
getProtocolVersion():返回報文的協議版本
getStatusLine():返回響應報文的第一行內容
getStatusLine().getStatusCode():返回報文的狀態碼
示例:
@Test public void testResponseMethod() { //模擬一個響應 HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); System.out.println("協議版本:" + response.getProtocolVersion()); System.out.println("協議信息:" + response.getStatusLine()); System.out.println("協議狀態碼:" + response.getStatusLine().getStatusCode()); }
3.Http報文頭部:
一個http報文頭部可以包含很多信息,如內容的長度、內容的類型等等各種各樣的信息。HttpResponse有着很多方法處理頭部的信息:
addHeader(String name, String value):增加一個頭部信息,一個key,一個value
getFirstHeader(String name):拿到第一個header
getLastHeader(String name):拿到最后一個header
getHeads(String name):拿到一個head數組
headerIterator(String name):拿到一個數組的迭代器
不僅如此,通過HeaderElementIterator我們還可以迭代出里面value的信息,看示例:
@Test public void testHeadMethod() { HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); response.addHeader("cookie", "c1=a;path=/;domain=localhost"); response.addHeader("cookie", "c2=b;path=/guo;domain=localhost:8080"); response.addHeader("cookie", "path=/ray;domain=localhost:3306"); System.out.println(response.getFirstHeader("cookie")); System.out.println(response.getLastHeader("cookie")); System.out.println("---------------------------------------------"); Header[] heads = response.getHeaders("cookie"); for(Header head : heads) System.out.println(head); System.out.println("---------------------------------------------"); HeaderIterator it = response.headerIterator(); while(it.hasNext()) System.out.println(it.next()); System.out.println("---------------------------------------------"); HeaderElementIterator hei = new BasicHeaderElementIterator(response.headerIterator()); while(hei.hasNext()) { HeaderElement element = hei.nextElement(); System.out.println(element.getName() + "=" + element.getValue()); NameValuePair[] params = element.getParameters(); for(NameValuePair name : params) System.out.println(name); } }
4.Http實體
實體是響應請求成功發送到客戶端時創建的,通過Entity我們可以拿到很多信息,看看下面的方法:
getContent():這個拿到響應的內容,前面我們就用過了
getContentType():拿到content的類型信息
getContentLength():拿到content的長度
通過EntityUtils類我們可以更加方法的拿到一些信息,看下面:
@Test public void testEntityMethod() throws Exception { StringEntity entity = new StringEntity("username=xujianguo", "utf-8"); System.out.println(entity.getContentType()); System.out.println(entity.getContentLength()); System.out.println(EntityUtils.toString(entity)); }
5.Http狀態碼
狀態碼 | 描述 |
200 | 請求成功 |
201 | 請求完成,結果是創建了新資源 |
202 | 請求被接受,但處理還沒完成 |
204 | 服務器已經完成了請求,但是沒有返回新的信息 |
300 | 存在多個可用的被請求資源 |
301 | 請求道的資源都會分配一個永久的url |
302 | 請求道的資源放在一個不同的url中臨時保存 |
304 | 請求的資源未更新 |
400 | 非法請求 |
401 | 未授權 |
403 | 禁止 |
404 | 找不到頁面 |