建立HTTP用戶端
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 也可以為用戶端配置請求的參數,作為所有請求的預設值RequestConfig requestConfig = RequestConfig.custom() .setConnectionRequestTimeout(5000) .setConnectTimeout(5000) .setSocketTimeout(5000) .setCookieSpec(CookieSpecs.DEFAULT) .build();CloseableHttpClient httpClient = HttpClients.custom() .setDefaultRequestConfig(requestConfig) .build();
建立GET請求
HttpGet httpGet = new HttpGet("http://localhost/index.html?param1=value1¶m2=value2");HttpClient提供URIBuilder工具類來簡化uri的建立
URI uri = null;try { uri= new URIBuilder() .setScheme("http") .setHost("localhost") .setPath("/index.html") .setParameter("param1", "value1") .setParameter("param2", "value2") .build();} catch (URISyntaxException e) { e.printStackTrace();}HttpGet httpGet = new HttpGet(uri);如果參數中含有中文,需將參數進行URLEncoding處理
URI uri = null;try { uri = new URIBuilder() .setScheme("http") .setHost("localhost") .setPath("/index.html") .setParameter("param1", URLEncoder.encode("中國", "UTF-8")) .setParameter("param2", "value2") .build();} catch (UnsupportedEncodingException | URISyntaxException e) { e.printStackTrace();}HttpGet httpGet = new HttpGet(uri);可以為單個請求設定一些配置
httpGet.setConfig(RequestConfig.DEFAULT);
建立POST請求
HttpPost httpPost = new HttpPost("http://www.baidu.com");httpPost的uri和RequestConfig設定同httpGet。可以為httpGet和httpPost設定訊息頭
httpPost.addHeader(HttpHeaders.CONTENT_TYPE, "application/octet-stream;charset=utf-8");httpGet.addHeader(HttpHeaders.ACCEPT, "application/xml");
執行請求
CloseableHttpResponse response = null;try { response = httpClient.execute(httpGet); // 擷取HTTP響應的狀態代碼 int status = response.getStatusLine().getStatusCode(); System.out.println(status);} catch (IOException e) { e.printStackTrace();} finally { try { if (response != null) response.close(); } catch (IOException e) { e.printStackTrace(); }}
CloseableHttpResponse response = null;try { CloseableHttpResponse response = httpClient.execute(httpPost); System.out.println(response.getStatusLine()); System.out.println(response.getAllHeaders()); System.out.println(response. getHeaders(HttpHeaders.CONTENT_TYPE); System.out.println(response.getEntity());} catch (IOException e) { e.printStackTrace();} finally { try { if (response != null) response.close(); } catch (IOException e) { e.printStackTrace(); }}
使用HttpEntity
當執行一個完整內容的Http請求或者Http請求已經成功,伺服器要發送響應到用戶端時,Http實體就會被建立。通過HttpResponse的getEntity()方法可以擷取HttpEntity,可以利用HttpEntity類的getContent方法來擷取實體的輸入資料流(java.io.InputStream),或者利用HttpEntity類的writeTo(OutputStream)方法來擷取輸出資料流,這個方法會把所有的內容寫入到給定的流中或則使用EntityUtils。
// 擷取響應的HttpEntityHttpEntity entity = response.getEntity();Header type = entity.getContentType();//Content-Typelong length = entity.getContentLength();//Content-LengthHeader encoding = entity.getContentEncoding();// 擷取響應的媒體類型, 例如:text/htmlString contentMimeType = ContentType.getOrDefault(entity).getMimeType();// 擷取響應的BODY部分String bodyAsString = EntityUtils.toString(entity);
InputStream instream = entity.getContent();try { // do something useful } finally { instream.close();}有些情況下,希望可以重複讀取Http實體的內容。這就需要把Http實體內容緩衝在記憶體或者磁碟上。最簡單的方法就是把Http Entity轉化成BufferedHttpEntity,這樣就把原Http實體的內容緩衝到了記憶體中。後面就可以重複讀取BufferedHttpEntity中的內容。
HttpEntity entity = response.getEntity(); if (entity != null) { entity = new BufferedHttpEntity(entity); }
類比提交Html表單請求
HttpPost httpPost = new HttpPost("http://www.baidu.com");// 拼接參數List<NameValuePair> formparams = new ArrayList<>();formparams.add(new BasicNameValuePair("username", "vip"));formparams.add(new BasicNameValuePair("password", "secret"));UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);httpPost.setEntity(entity);
發送二進位
httpPost.addHeader("Content-Type", "application/octet-stream;charset=utf-8");httpPost.setEntity(new ByteArrayEntity(bytes));
ResponseHandler
最簡單也是最方便的處理http響應的方法就是使用ResponseHandler介面,這個介面中有handleResponse(HttpResponse response)方法。使用這個方法,使用者完全不用關心http連線管理員。當使用ResponseHandler時,HttpClient會自動地將Http串連釋放給Http管理器,即使http請求失敗了或者拋出了異常。
CloseableHttpClient httpclient = HttpClients.createDefault();HttpGet httpget = new HttpGet("http://www.yeetrack.com/json");ResponseHandler<MyJsonObject> rh = new ResponseHandler<MyJsonObject>() {@Overridepublic 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);}};//設定responseHandler,當執行http方法時,就會返回MyJsonObject對象。MyJsonObject myjson = client.execute(httpget, rh);
HttpClient已經實現了安全執行緒。所以在執行個體化HttpClient時,也要支援為多個請求使用。當一個CloseableHttpClient的執行個體不再被使用,並且它的作用範圍即將失效,和它相關的串連必須被關閉,關閉方法可以調用CloseableHttpClient的close()方法。
CloseableHttpClient httpclient = HttpClients.createDefault();try {<...>} finally {//關閉串連httpclient.close();}HttpClient介面沒有對Http請求的過程做特別的限制和詳細的規定,串連管理、狀態管理、授權資訊和重新導向處理這些功能都單獨實現。這樣使用者就可以更簡單地拓展介面的功能(比如緩衝響應內容)。
一般說來,HttpClient實際上就是一系列特殊的handler或者說策略介面的實現,這些handler(測試介面)負責著處理Http協議的某一方面,比如重新導向、認證處理、有關串連持久性和keep alive期間的決策。這樣就允許使用者使用自訂的參數來代替預設配置,實現個人化的功能。
ConnectionKeepAliveStrategy keepAliveStrat = new DefaultConnectionKeepAliveStrategy() {@Overridepublic long getKeepAliveDuration(HttpResponse response,HttpContext context) {long keepAlive = super.getKeepAliveDuration(response, context);if (keepAlive == -1) {//如果伺服器沒有設定keep-alive這個參數,我們就把它設定成5秒keepAlive = 5000;}return keepAlive;}};//定製我們自己的httpclientCloseableHttpClient httpclient = HttpClients.custom().setKeepAliveStrategy(keepAliveStrat).build();參考: http://www.yeetrack.com/?p=779