HttpURLConnection與HttpClient學習
轉載HttpURLConnection與HttpClient淺析
一、HttpURLConnection的使用
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL;public class HttpURLConnectionUtil { private static final Logger logger = LoggerFactory.getLogger(HttpURLConnection.class); /** * get請求 * @param urlStr 請求地址 * @param param 請求參數 */ public static void Get(String urlStr,String param) { try { urlStr = urlStr + "?"+param; // 1.獲取訪問地址 URL url = new URL(urlStr); // 2.獲取網絡訪問對象 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); /* 3.設置請求參數(過期時間、輸入/輸出流、訪問方式),以流的形式進行連接 */ // 設置是否向HttpURLConnection輸出 connection.setDoOutput(false); // 設置是否向HttpURLConnection讀入 connection.setDoInput(true); // 設置請求方式 connection.setRequestMethod("GET"); // 設置是否使用緩存 connection.setUseCaches(true); // 設置HttpURLConnection實例是否自動執行HTTP重定向 connection.setInstanceFollowRedirects(true); // 設置超時時間 connection.setConnectTimeout(3000); // 連接 connection.connect(); // 4.得到相應狀態碼的返回值 int responseCode = connection.getResponseCode(); logger.info("Get-responseCode:"+responseCode); // 5.如果返回值正常,數據在網絡中是以流的形式得到服務器返回的數據 String msg = ""; // 正常響應 if(responseCode == 200) { // 從流中讀取數據 BufferedReader reader = new BufferedReader( new InputStreamReader(connection.getInputStream()) ); String line = null; // 循環從流中讀取 while ((line = reader.readLine()) != null) { msg += line + "\n"; } reader.close(); } // 6.斷開連接,釋放資源 connection.disconnect(); // 響應數據 System.out.println(msg); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * post請求 * @param urlStr 請求地址 * @param param 請求參數 */ public static void Post(String urlStr, String param) { try { // 1.獲取訪問地址 URL url = new URL(urlStr); // 2.獲取網絡訪問對象 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); /* 3.設置請求參數(過期時間、輸入/輸出流、訪問方式),以流的形式進行連接 */ // 設置請求方式 connection.setRequestMethod("POST"); // 設置超時時間 connection.setConnectTimeout(3000); // 設置是否向HttpURLConnection輸出 connection.setDoOutput(true); // 設置是否向HttpURLConnection讀入 connection.setDoInput(true); // 設置是否使用緩存 connection.setUseCaches(false); // 設置HttpURLConnection實例是否自動執行HTTP重定向 connection.setInstanceFollowRedirects(true); // 設置使用標準編碼格式編碼參數的名-值對 connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); // 連接 connection.connect(); /* 4. 處理輸入輸出 */ // 寫入參數到請求中 OutputStream out = connection.getOutputStream(); out.write(param.getBytes()); out.flush(); out.close(); // 從連接中讀取響應數據 String msg = ""; int responseCode = connection.getResponseCode(); logger.info("Post-reponseCode:"+responseCode); if(responseCode == 200) { BufferedReader reader = new BufferedReader( new InputStreamReader(connection.getInputStream()) ); String line = ""; while ((line = reader.readLine()) != null) { msg += line + "\n"; } reader.close(); } connection.disconnect(); System.out.println(msg); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { String urlStr = "http://localhost:8080/aa"; String param = "name=nana"; Get(urlStr,param); Post(urlStr,param); } }
說明:
- HttpURLConnection對象不能直接構造,需要通過URL類中的openConnection()方法來獲得。
- HttpURLConnection的connect()函數,實際上只是建立了一個與服務器的TCP連接,並沒有實際發送HTTP請求。HTTP請求實際上直到我們獲取服務器響應數據(如調用getInputStream()、getResponseCode()等方法)時才正式發送出去。
- 對HttpURLConnection對象的配置都需要在connect()方法執行之前完成。
- HttpURLConnection是基於HTTP協議的,其底層通過socket通信實現。如果不設置超時(timeout),在網絡異常的情況下,可能會導致程序僵死而不繼續往下執行。
- HTTP正文的內容是通過OutputStream流寫入的, 向流中寫入的數據不會立即發送到網絡,而是存在於內存緩沖區中,待流關閉時,根據寫入的內容生成HTTP正文。
- 調用getInputStream()方法時,返回一個輸入流,用於從中讀取服務器對於HTTP請求的返回信息。
- 我們可以使用HttpURLConnection.connect()方法手動的發送一個HTTP請求,但是如果要獲取HTTP響應的時候,請求就會自動的發起,比如我們使用HttpURLConnection.getInputStream()方法的時候,所以完全沒有必要調用connect()方法。
二、HttpURLConnection的使用
1.HttpClient簡介:
在一般情況下,如果只是需要向Web站點的某個簡單頁面提交請求並獲取服務器響應,HttpURLConnection完全可以勝任。但在絕大部分情況下,Web站點的網頁可能沒這麽簡單,這些頁面並不是通過一個簡單的URL就可訪問的,可能需要用戶登錄而且具有相應的權限才可訪問該頁面。在這種情況下,就需要涉及Session、Cookie的處理了,如果打算使用HttpURLConnection來處理這些細節,當然也是可能實現的,只是處理起來難度就大了。
為了更好地處理向Web站點請求,包括處理Session、Cookie等細節問題,Apache開源組織提供了一個HttpClient項目,看它的名稱就知道,它是一個簡單的HTTP客戶端(並不是瀏覽器),可以用於發送HTTP請求,接收HTTP響應。但不會緩存服務器的響應,不能執行HTML頁面中嵌入的Javascript代碼;也不會對頁面內容進行任何解析、處理。
簡單來說,HttpClient就是一個增強版的HttpURLConnection,HttpURLConnection可以做的事情HttpClient全部可以做;HttpURLConnection沒有提供的有些功能,HttpClient也提供了,但它只是關註於如何發送請求、接收響應,以及管理HTTP連接。
2. HttpClient的使用:
- 創建HttpClient對象。
- 如果需要發送GET請求,創建HttpGet對象;如果需要發送POST請求,創建HttpPost對象。
- 如果需要發送請求參數,可調用HttpGet、HttpPost共同的setParams(HttpParams params)方法來添加請求參數;對於HttpPost對象而言,也可調用setEntity(HttpEntity entity)方法來設置請求參數。
- 調用HttpClient對象的execute(HttpUriRequest request)發送請求,執行該方法返回一個HttpResponse。
- 調用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可獲取服務器的響應頭;調用HttpResponse的getEntity()方法可獲取HttpEntity對象,該對象包裝了服務器的響應內容。程序可通過該對象獲取服務器的響應內容。
3. HttpClient的使用例子:
import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; public class HttpClientUtil { private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class); public static void Get(String urlStr,String param) { // 1.創建HttpClient對象 CloseableHttpClient httpClient = HttpClientBuilder.create().build(); // 2.創建HttpGet對象 HttpGet httpGet = new HttpGet(urlStr); CloseableHttpResponse response= null; try { // 3.創建GET請求 response = httpClient.execute(httpGet); System.out.println(response.getStatusLine()); // 4.獲取響應實體 HttpEntity entity = response.getEntity(); // 5.處理響應實體 if (entity != null) { logger.info("長度:" + entity.getContentLength()); logger.info("內容:" + EntityUtils.toString(entity)); } } catch (IOException e) { e.printStackTrace(); } finally { // 6.釋放資源 try { response.close(); httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void Post(String urlStr, String param) { // 1.創建HttpClient對象 CloseableHttpClient httpClient = HttpClientBuilder.create().build(); // 2.創建HttpPost對象 HttpPost post = new HttpPost(urlStr); // 3.設置POST請求傳遞參數 List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("name","wln")); try { UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params); post.setEntity(entity); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } // 4.執行請求並處理相應 try { CloseableHttpResponse response = httpClient.execute(post); HttpEntity entity = response.getEntity(); if (entity != null) { logger.info("響應內容:"+EntityUtils.toString(entity)); } response.close(); } catch (IOException e) { e.printStackTrace(); } finally { // 釋放資源 try { httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { String urlStr = "http://localhost:8080/bb"; String param = ""; Get(urlStr,param); Post(urlStr,param); } }
註:使用時要導入下面的jar包
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.1</version> </dependency>
4.說明
HttpClient相比傳統JDK自帶的URLConnection,增加了易用性和靈活性,它不僅使客戶端發送HTTP請求變得容易,而且也方便了開發人員測試接口(基於Http協議的),即提高了開發的效率,也方便提高代碼的健壯性。
HttpURLConnection與HttpClient學習