【傳輸協議】HttpClient基本使用
最近工作中是做了一個handoop的hdfs系統的檔案瀏覽器的功能,是利用webhdfs提供的rest api來訪問hdfs來與hdfs進行互動的,其中大量使用HttpClient,之前一直很忙,沒什麼時間來總結,今天閒下來了,可以來好好總結一下這個東西了。
1.HttpClient簡介
http協議可以說是現在Internet上面最重要,使用最多的協議之一了,越來越多的java應用需要使用http協議來訪問網路資源,特別是現在rest api的流行,HttpClient 是 Apache Jakarta Common 下的子專案,用來提供高效的、最新的、功能豐富的支援 HTTP 協議的客戶端程式設計工具包,並且它支援 HTTP 協議最新的版本和建議。HttpClient 已經應用在很多的專案中,比如 Apache Jakarta 上很著名的另外兩個開源專案 Cactus 和 HTMLUnit 都使用了 HttpClient,很多的java的爬蟲也是透過HttpClient實現的,研究HttpClient對我們來說是非常重要的。
2.HttpClient不是瀏覽器
很多人覺得既然HttpClient是一個HTTP客戶端程式設計工具,很多人把他當做瀏覽器來理解,但是其實HttpClient不是瀏覽器,它是一個HTTP通訊庫,因此它只提供一個通用瀏覽器應用程式所期望的功能子集,最根本的區別是HttpClient中沒有使用者介面,瀏覽器需要一個渲染引擎來顯示頁面,並解釋使用者輸入,例如滑鼠點選顯示頁面上的某處,有一個佈局引擎,計算如何顯示HTML頁面,包括級聯樣式表和影像。javascript直譯器執行嵌入HTML頁面或從HTML頁面引用的javascript程式碼。來自使用者介面的事件被傳遞到javascript直譯器進行處理。除此之外,還有用於外掛的介面,可以處理Applet,嵌入式媒體物件(如pdf檔案,Quicktime電影和Flash動畫)或ActiveX控制元件(可以執行任何操作)。HttpClient只能以程式設計的方式透過其API用於傳輸和接受HTTP訊息。HttpClient也是完全內容不可知的。
另一個主要區別是對錯誤輸入或HTTP標準違規的容忍。 需要允許無效的使用者輸入,以使瀏覽器使用者友好。 還需要對從伺服器檢索的畸形文件的容忍度,以及在執行協議時伺服器行為的缺陷,使盡可能多的使用者可訪問的網站。 然而,HttpClient努力在預設情況下儘可能接近並遵守HTTP標準規範和相關標準。 它還提供了一些手段來放鬆規範所施加的一些限制,這些限制允許或要求與不相容的HTTP源或代理伺服器相容。
3.HttpClient入門使用
注意這個版本主要是基於HttpClient4.5.2版本的來講解的,也是現在最新的版本,之所以要提供版本說明的是因為HttpClient 3版本和HttpClient 4版本差別還是很多大的,基本HttpClient裡面的介面都變了,你把HttpClient 3版本的程式碼拿到HttpClient 4上面都執行不起來,會報錯的。所以這兒一定要注意,好了廢話不多說了,開始。
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/html
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
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();
}}
關閉內容流和關閉響應之間的區別是:前者將嘗試透過消耗實體內容來保持底層連線活動,而後者立即關閉並丟棄連線
至此,一個基本的HttpClient的使用的例子已經成功完成,文章還有很多不足,希望得到大家的批評和指正。
相關文章
- 傳輸層協議2024-09-23協議
- 網路傳輸協議2018-02-01協議
- 超文字傳輸協議2018-05-30協議
- 4種傳輸協議設定,檔案傳輸協議如何選擇?2020-08-21協議
- TCP傳輸協議詳解2019-04-08TCP協議
- HTTP超文字傳輸協議2020-12-21HTTP協議
- [TCPIP] 傳輸控制協議 Note2015-11-16TCP協議
- 還在使用檔案傳輸協議傳輸機密檔案?你可能是對檔案傳輸協議有什麼誤會2020-06-30協議
- 傳輸層協議 TCP 和 UDP2020-06-24協議TCPUDP
- Raysync檔案傳輸協議(FTP)2019-05-29協議FTP
- 檔案傳輸協議介紹2019-06-11協議
- 如何看待鐳速傳輸的Raysync高速傳輸協議?2020-10-27協議
- Android使用Socket(Tcp/Udp)協議進行資料傳輸(傳輸大檔案)2016-08-31AndroidTCPUDP協議
- 在java中使用SFTP協議安全的傳輸檔案2020-10-12JavaFTP協議
- 伺服器傳輸協議介紹2022-10-20伺服器協議
- Git傳輸協議的對比分析2024-03-13Git協議
- 流媒體傳輸協議之 RTP (上篇)2021-02-09協議
- 流媒體傳輸協議之 RTP(下篇)2021-02-10協議
- 訊息佇列面試解析 - 傳輸協議2021-12-12佇列面試協議
- 流媒體技術之傳輸協議2015-05-31協議
- FreeBSD超文字傳輸協議HTTP(轉)2007-08-11協議HTTP
- 檔案傳輸協議的五種安全檔案傳輸替代方案2023-03-03協議
- 支援斷點續傳的大檔案傳輸協議2019-06-12斷點協議
- 網路協議之:基於UDP的高速資料傳輸協議UDT2021-12-13協議UDP
- netty系列之:在netty中使用native傳輸協議2022-06-29Netty協議
- TCP傳輸協議如何進行流量控制?2019-08-15TCP協議
- WebRTC:資料傳輸相關協議簡介2019-07-17Web協議
- TCP/IP五層模型-傳輸層-TCP協議2021-01-16TCP模型協議
- netty系列之:kequeue傳輸協議詳解2022-07-04Netty協議
- DDTP 分散式資料傳輸協議白皮書2021-11-04分散式協議
- 用python實現TCP協議傳輸功能2020-09-30PythonTCP協議
- IP協議號和傳輸層埠號【Z】2010-12-29協議
- Socket開發框架之資料傳輸協議2016-03-29框架協議
- 傳輸控制協議/網際網路協議(TCP / IP)是什麼意思?-VeCloud2020-10-15協議TCPCloud
- Java呼叫使用SSL/HTTPS協議來傳輸的axis webservice服務2017-03-20JavaHTTP協議Web
- 【傳輸協議】http協議GET與POST傳遞資料的最大長度能夠達到多少2018-04-18協議HTTP
- HttpClient 基本功能的使用2011-04-29HTTPclient
- 深入理解 web 協議(一)- http 包體傳輸2019-10-21Web協議HTTP