HTTP協議的發展史沒有了解,是給予請求與響應模式的、無鏈接、無狀態的應用層的協議。php
#HTTP協議
<br/> ##HTTP協議的URL HTTP URL(URL是一種特殊類型的URI,包含了敢於查找某個資源的足夠的信息)的格式以下:html
http://host[":"port][abs_path]
http表示要經過HTTP協議來定位網絡資源;host表示合法的Internet主機域名或者IP地址;port指定一個端口號,爲空則使用缺省端口80;abs_path指定請求資源的URI;若是URL中沒有給出abs_path,那麼當它做爲請求URI時,必須以「/」的形式給出,一般這個工做瀏覽器自動幫咱們完成。java
##HTTP協議的請求和響應體 算法
下圖是使用HttpWatchPro工具查看到的一個Headers數據庫
#HttpURLConnection和HttpClient 利用Http協議聯網
<br/> ##HttpURLConnection基本功能的使用apache
使用 HttpURLConnection須要如下 6 個步驟:瀏覽器
根據以上步驟,咱們來編寫用GET方法來取得某網頁內容的代碼。緩存
1.首先使用構造函數獲取URL,URL請求的類別分爲二類,GET與POST請求。兩者的區別在於:服務器
get請求能夠獲取靜態頁面,也能夠把參數放在URL字串後面,傳遞給servlet,網絡
post與get的不一樣之處在於post的參數不是放在URL字串裏面,而是放在http請求的正文內。
<!-- lang: java -->
URL url = new URL("http://192.168.1.151:8080/SHE/think");
2.得到HttpURLConnection 實例
<!-- lang: java --> HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
3.設置HttpURLConnection 實例
設置是否向httpUrlConnection輸出,由於這個是post請求,參數要放在http正文內,所以須要設爲true, 默認狀況下是false;
<!-- lang: java --> urlConn.setDoOutput(true);
設置是否從httpUrlConnection讀入,默認狀況下是true;
<!-- lang: java --> urlConn.setDoInput(true);
設置緩存, Post 請求不能使用緩存
<!-- lang: java --> urlConn.setUseCaches(false);
設定請求的方法類型,默認是GET
<!-- lang: java --> urlConn.setRequestMethod("POST");
設置鏈接主機超時(單位:毫秒)
<!-- lang: java --> urlCon.setConnectTimeout(30000);
設置從主機讀取數據超時(單位:毫秒)
<!-- lang: java --> urlCon.setReadTimeout(30000);
-設置GET方法對應HTTP請求中的消息報頭(可選):
<!-- lang: java --> httpurlconnection.setRequestProperty("User-Agent",Commons.User_Agent); httpurlconnection.setRequestProperty("Accept",Commons.Accept); httpurlconnection.setRequestProperty("Accept-Charset",Commons.Accept_Charset); httpurlconnection.setRequestProperty("AcceptLanguage",Commons.Accept_Language; httpurlconnection.setRequestProperty("Connection",Commons.Connection); httpurlconnection.setRequestProperty("Keep-Alive",Commons.Keep_Alive);
POST請求設定傳送的內容類型是可序列化的java對象 ,若是不設此項,在傳送序列化對象時,當WEB服務默認的不是這種類型時可能拋java.io.EOFException
<!-- lang: java --> urlConn.setRequestProperty("Content-type","application/x-java-serialized-object");
4.鏈接HttpURLConnection 實例
普通鏈接,connect()
<!-- lang: java --> urlConnection.connect();
2B鏈接,得到輸出流,向服務器輸出數據(不用調用connect())
<!-- lang: java --> String params = "username=sbCode&password=123456"; OutputStream outStream = httpUrlConnection.getOutputStream(); outStream .write(params.getBytes()); outStream.flush();
服務器端可經過request.getParameter("username");得到傳入服務器的數據。
文藝鏈接,調用HttpURLConnection鏈接對象的getInputStream()函數, 得到服務器的數據,將內存緩衝區中封裝好的完整的HTTP請求電文發送到服務端。
<!-- lang: java --> InputStream inStream = uRLConnection.getInputStream();
能夠經過int responseCode = urlConnection.getResponseCode();得到服務器的狀態碼,若是爲200就是正常。注意最後關閉流對象
5.釋放鏈接
<!-- lang: java --> uRLConnection.disconnect();
6.處理得到InputStream
<!-- lang: java --> ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] data = new byte[1024]; int len = 0; String result = ""; if(inputStream != null){ try { while((len = inputStream.read(data))!=-1){ byteArrayOutputStream.write(data,0,len); } result = new String(byteArrayOutputStream.toByteArray(),encode); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
##HttpClient的入門 <br/> ###HttpClient 功能介紹
如下列出的是 HttpClient 提供的主要的功能:
###HttpClient 基本功能的使用
###GET 方法
使用 HttpClient 須要如下 6 個步驟:
<br/> 根據以上步驟,咱們來編寫用GET方法來取得某網頁內容的代碼。
大部分狀況下 HttpClient 默認的構造函數已經足夠使用。
<!-- lang: java --> HttpClient httpClient = new HttpClient();
建立GET方法的實例。在GET方法的構造函數中傳入待鏈接的地址便可。用GetMethod將會自動處理轉發過程,若是想要把自動處理轉發過程去掉的話,能夠調用方法setFollowRedirects(false)。
<!-- lang: java --> GetMethod getMethod = new GetMethod("http://www.ibm.com/");
調用實例httpClient的executeMethod方法來執行getMethod。因爲是執行在網絡上的程序,在運行executeMethod方法的時候,須要處理兩個異常,分別是HttpException和IOException。引發第一種異常的緣由主要多是在構造getMethod的時候傳入的協議不對,好比不當心將"http"寫成"htp",或者服務器端返回的內容不正常等,而且該異常發生是不可恢復的;第二種異常通常是因爲網絡緣由引發的異常,對於這種異常 (IOException),HttpClient會根據你指定的恢復策略自動試着從新執行executeMethod方法。HttpClient的恢復策略能夠自定義(經過實現接口HttpMethodRetryHandler來實現)。經過httpClient的方法setParameter設置你實現的恢復策略,本文中使用的是系統提供的默認恢復策略,該策略在碰到第二類異常的時候將自動重試3次。executeMethod返回值是一個整數,表示了執行該方法後服務器返回的狀態碼,該狀態碼能表示出該方法執行是否成功、須要認證或者頁面發生了跳轉(默認狀態下GetMethod的實例是自動處理跳轉的)等。
<!-- lang: java --> //設置成了默認的恢復策略,在發生異常時候將自動重試3次,在這裏你也能夠設置成自定義的恢復策略 getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,new DefaultHttpMethodRetryHandler()); //執行getMethod int statusCode = httpClient.executeMethod(getMethod); if (statusCode != HttpStatus.SC_OK) { System.err.println("Method failed: " + getMethod.getStatusLine()); }
在返回的狀態碼正確後,便可取得內容。取得目標地址的內容有三種方法:第一種,getResponseBody,該方法返回的是目標的二進制的byte流;第二種,getResponseBodyAsString,這個方法返回的是String類型,值得注意的是該方法返回的String的編碼是根據系統默認的編碼方式,因此返回的String值可能編碼類型有誤,在本文的"字符編碼"部分中將對此作詳細介紹;第三種,getResponseBodyAsStream,這個方法對於目標地址中有大量數據須要傳輸是最佳的。在這裏咱們使用了最簡單的getResponseBody方法。
<!-- lang: java --> byte[] responseBody = method.getResponseBody();
釋放鏈接。不管執行方法是否成功,都必須釋放鏈接。
<!-- lang: java --> method.releaseConnection();
處理內容。在這一步中根據你的須要處理內容,在例子中只是簡單的將內容打印到控制檯。
<!-- lang: java --> System.out.println(new String(responseBody));
下面是程序的完整代碼
<!-- lang: java --> import java.io.IOException; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.params.HttpMethodParams; public class GetSample{ public static void main(String[] args) { //構造HttpClient的實例 HttpClient httpClient = new HttpClient(); //建立GET方法的實例 GetMethod getMethod = new GetMethod("http://www.ibm.com"); //使用系統提供的默認的恢復策略 getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler()); try { //執行getMethod int statusCode = httpClient.executeMethod(getMethod); if (statusCode != HttpStatus.SC_OK) { System.err.println("Method failed: "+ getMethod.getStatusLine()); } //讀取內容 byte[] responseBody = getMethod.getResponseBody(); //處理內容 System.out.println(new String(responseBody)); } catch (HttpException e) { //發生致命的異常,多是協議不對或者返回的內容有問題 System.out.println("Please check your provided http address!"); e.printStackTrace(); } catch (IOException e) { //發生網絡異常 e.printStackTrace(); } finally { //釋放鏈接 getMethod.releaseConnection(); } } }
###POST方法
根據RFC2616,對POST的解釋以下:POST方法用來向目的服務器發出請求,要求它接受被附在請求後的實體,並把它看成請求隊列(Request-Line)中請求URI所指定資源的附加新子項。POST被設計成用統一的方法實現下列功能:
調用HttpClient中的PostMethod與GetMethod相似,除了設置PostMethod的實例與GetMethod有些不一樣以外,剩下的步驟都差很少。在下面的例子中,省去了與GetMethod相同的步驟,只說明與上面不一樣的地方。
<!-- lang: java --> String url = "http://www.newsmth.net/bbslogin2.php"; PostMethod postMethod = new PostMethod(url); // 填入各個表單域的值 NameValuePair[] data = { new NameValuePair("id", "youUserName"), new NameValuePair("passwd", "yourPwd") }; // 將表單的值放入postMethod中 postMethod.setRequestBody(data); // 執行postMethod int statusCode = httpClient.executeMethod(postMethod); // HttpClient對於要求接受後繼服務的請求,象POST和PUT等不能自動處理轉發 // 301或者302 if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) { // 從頭中取出轉向的地址 Header locationHeader = postMethod.getResponseHeader("location"); String location = null; if (locationHeader != null) { location = locationHeader.getValue(); System.out.println("The page was redirected to:" + location); } else { System.err.println("Location field value is null."); } return; }
###使用HttpClient過程當中常見的一些問題 <br/> ###字符編碼
某目標頁的編碼可能出如今兩個地方,第一個地方是服務器返回的http頭中,另一個地方是獲得的html/xml頁面中。
###處理代理服務器
HttpClient中使用代理服務器很是簡單,調用HttpClient中setProxy方法就能夠,方法的第一個參數是代理服務器地址,第二個參數是端口號。另外HttpClient也支持SOCKS代理。
<!-- lang: java --> httpClient.getHostConfiguration().setProxy(hostName,port);
參考資料:
Commons logging包含了各類各樣的日誌API的實現,讀者能夠經過站點獲得詳細的內容
Commons codec包含了一些通常的解碼/編碼算法。包含了語音編碼、十六進制、Base64和URL編碼等,經過站點能夠獲得詳細的內容
HTTPClient的主頁,能夠在這裏獲得關於HttpClient更加詳細的信息