標籤:ext nbu 訊息 發送請求 while util 協議 不用 search
HttpClient 該知道不該知道的一些事一、簡介:
- Apache開源項目: http://hc.apache.org/
- 基於HTTP協議提供強大的支援,構建HTTP用戶端應用程式
- 執行HTTP協議時,包含了HTTP請求和響應不同狀態,可以對關鍵參數設定和擷取
二、HTTP協議(掃盲)
- HTTP請求包含三部分,分別由請求行(要求方法)、要求標頭(訊息報文)、請求本文組成。
- HTTP請求詳解:
三、URI URL和URN區別:
- URI(Uniform Resource Identifier) 統一資源標識符
- URL(Uniform Resource Locator) 統一資源定位器
- URN(Uniform Resource Name) 統一資源名稱
- 整體關係:
比如有一個虛擬位址,首先這是一個URI:http://bitpoetry.io/posts/hello.html#intro我們分析:http:// 是定義如何訪問資源的方式。bitpoetry.io/posts/hello.html是資源存放的位置,那麼,在這個栗子中,#intro是資源。
- URL是URI的一個子集,告訴我們訪問網路位置的方式,
http://bitpoetry.io/posts/hello.html
- URN是URI的子集,包括名字(給定的命名空間內),但不包括訪問方式
bitpoetry.io/posts/hello.html#intro
四、調用步驟:
- 建立 HttpClient 對象
- 建立要求方法的執行個體,並指定URL。
- GET 請求,建立 HttpGet 對象
- POST 請求,建立 HttpPost 對象
- 調用 SetParams(HttpParams params) 方法來添加請求參數, 對於 HttpPost 對象而言,也可以調用 setEntity(HttpEntity entity) 方法來佈建要求參數
- 調用 HttpClient 對象的 execute(HttpUriRequest request) 發送請求,該方法返回一個 HttpResponse
- 調用 HttpResponse 的 getAllHeaders()、getHeaders(String name) 等方法可擷取伺服器的回應標頭;調用 HttpResponse 的 getEntity() 方法可擷取 HttpEntity 對象,該對象封裝了伺服器的相應內容。程式可以通過擷取伺服器的相應內容
- 釋放串連,無論執行方法是否成功,都必須釋放串連
例如: 五、調用細節:
- HttpClient提供了URIBuilder類來簡化和修改請求URI
http://image.baidu.com/search/detail?ct=503316480&word=scheme 可以有如下寫法:URI uri = new URIBuilder() .setScheme("http") //設定scheme .setHost("image.baidu.com")//set host .setPath("/search/detail")// set path .setParameter("ct","503316480")// set param .setParameter("word","scheme") .build();
response.getProtocolVersion() // 協議response.getStatusLine().getStatusCode() //狀態代碼response.getStatusLine().getReasonPhrase()//表單含義
- 擷取給定類型的所有頭部資訊最有效方式是使用HeaderIterator介面:
public static void main(String[] args) { HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); response.addHeader("Set-Cookie", "c1=a; path=/; domain=localhost"); response.addHeader("Set-Cookie", "c2=b; path=\"/\", c3=c; domain=\"localhost\""); HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator("Set-Cookie")); while (it.hasNext()) { HeaderElement elem = it.nextElement(); System.out.println(elem.getName() + " = " + elem.getValue()); NameValuePair[] params = elem.getParameters(); for (int i = 0; i < params.length; i++) { System.out.println(" " + params[i]); } }}運行輸出:c1 = a path=/ domain=localhostc2 = b path=/c3 = c domain=localhost
- 為了保證系統資源被正確地釋放,我們要麼管理HTTP實體流,要麼關閉http響應。
- 關閉HTTP實體內容流和關閉HTTP響應的區別,前者通過消耗掉HTTP實體內容來保持相關HTTP串連,然而後者會立即關閉,丟棄HTTP串連。
- HttpClient 推薦使用 HttpEntity 的 getContent() 方法或者 HttpEntity 的 writeTo(OutputStream) 方法讀取Http實體內容。
- EntityUtils 提供的方法可以以字串或者位元組數組的形式讀取 Http 實體,但是一般不建議,確保相應的實體長度不大。
- 希望把 Http 實體內容緩衝在記憶體或者磁碟上,最簡單方法就是把 Http Entity 轉化為 BufferedHttpEntity,
CloseableHttpResponse response = <...>HttpEntity entity = response.getEntity();if (entity != null) { entity = new BufferedHttpEntity(entity);}
- HttpClient 提供了一些類,這些類可以通過http串連高效地輸出Http實體內容。
- HttpClient 提供的這幾個類涵蓋的常見的資料類型,如String,byte 數組,輸入資料流,和檔案類型:StringEntity,ByteArrayEntity,InputStreamEntity,FileEntity。
File file = new File("somefile.txt");FileEntity entity = new FileEntity(file, ContentType.create("text/plain", "UTF-8")); HttpPost httppost = new HttpPost("http://localhost/action.do");httppost.setEntity(entity);
- 請注意由於 InputStreamEntity 只能從下層的資料流中讀取一次,所以它是不能重複的。推薦,通過繼承 HttpEntity 這個自包含的類來自訂HttpEntity 類,而不是直接使用 InputStreamEntity 這個類。FileEntity 就是一個很好的起點(FileEntity 就是繼承的 HttpEntity)。
- 類比 HTML 表單提交
List<NameValuePair> formparams = new ArrayList<NameValuePair>();formparams.add(new BasicNameValuePair("param1", "value1"));formparams.add(new BasicNameValuePair("param2", "value2"));UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);HttpPost httppost = new HttpPost("http://localhost/handler.do");httppost.setEntity(entity);
StringEntity entity = new StringEntity("important message", ContentType.create("plain/text", Consts.UTF_8));entity.setChunked(true);HttpPost httppost = new HttpPost("http://localhost/acrtion.do");httppost.setEntity(entity);
- 處理http響應的方法就是使用ResponseHandler介面,這個介面中有handleResponse(HttpResponse response)方法。使用這個方法,使用者完全不用關心http連線管理員。當使用ResponseHandler時,HttpClient會自動地將Http串連釋放給Http管理器,即使http請求失敗了或者拋出了異常。
CloseableHttpClient httpclient = HttpClients.createDefault();HttpGet httpget = new HttpGet("http://localhost/json"); ResponseHandler<MyJsonObject> rh = new ResponseHandler<MyJsonObject>() { @Override public JsonObject handleResponse( final HttpResponse response) throws IOException { StatusLine statusLine = response.getStatusLine(); HttpEntity entity = response.getEntity(); if (statusLine.getStatusCode() >= 300) { throw new HttpResponseException( statusLine.getStatusCode(), statusLine.getReasonPhrase()); } if (entity == null) { throw new ClientProtocolException("Response contains no content"); } Gson gson = new GsonBuilder().create(); ContentType contentType = ContentType.getOrDefault(entity); Charset charset = contentType.getCharset(); Reader reader = new InputStreamReader(entity.getContent(), charset); return gson.fromJson(reader, MyJsonObject.class); }};MyJsonObject myjson = client.execute(httpget, rh);
HttpClient 該知道一些概念