JavaWeb學習篇之----HTTP協議詳解

簡介:

 

HTTP是hypertexttransfer protocol(超文本傳輸協議)的簡寫,它是TCP/IP協議的一個應用層協議,用於定義WEB瀏覽器與WEB服務器之間交換數據的過程。
HTTP協議是學習JavaWEB開發的基石,不深刻了解HTTP協議,就不能說掌握了WEB開發,更沒法管理和維護一些複雜的WEB站點。HTTP協議的版本:HTTP/1.0、HTTP/1.1
 
HTTP/1.0和HTTP/1.1的區別
HTTP1.0協議:客戶端與web服務器創建鏈接後,只能得到一個web資源,在獲取資源以後就斷開鏈接。
HTTP1.1協議:容許客戶端與web服務器創建鏈接後,在一個鏈接上獲取多個web資源都不會斷開鏈接,除非是訪問出錯和手動斷開鏈接。
 
下面使用telnet命令來舉例說明:
首先啓動telnet來鏈接上tomcat服務器,而後輸入請求內容獲取資源:
這裏可能會出現一些問題:詳情請見: http://www.oschina.net/question/234345_53824
同時咱們還須要在tomcat的webapp目錄中新建一個aa工程,在該工程中新建一個index.html文件,文件中輸入點內容。
鏈接上tomcat服務器以後,輸入命令: GET  /aa/index.html  HTTP/1.0
 
 
從上圖能夠查看在使用HTTP/1.0的時候,訪問到了數據以後就斷開了鏈接。
 
下面再來使用HTTP/1.1測試一下:輸入命令: GET  /aa/index.html  HTTP/1.1
 
 
當獲取玩數據以後並無斷開鏈接,還能夠繼續輸入命令進行請求。
 
經過上面的例子看以看到HTTP/1.0和HTTP/1.1的區別了。
 
下面再來看一下一個簡單的web頁面中每一個資源標籤都會發送一次請求,這裏咱們來驗證的話須要輔助工具了:HttpWatch Pro工具,這就是一個web抓包工具,能夠監測http請求的。安裝很簡單的。咱們這裏使用IE瀏覽器測試:http://localhost:8080/aa/index.html:
 
 
咱們看到只有一次Get請求。下面咱們在/aa/index.html文件中添加內容:
 
[html]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. <img src="1.jpg"/>  
  2. <img src="2.jpg"/>  
  3. <img src="3.jpg"/>  
 
這是使用了三個圖片標籤,咱們再次訪問:http://localhost:8080/aa/index.html
 


咱們能夠看到發生了四次請求,其中有三次是來請求圖片資源的。
同理:腳本標籤也是同樣,因此像一些資源標籤會發生一次請求的,因此咱們在設計網站的時候爲了網頁的訪問性能,我可能會將多個資源整合起來,好比:三張圖片可能整合到一張,三個腳本文件可能整合到一個文件中。這些舉措都是爲了訪問性能。固然這種狀況確定是視狀況而定的。
 

HTTP的請求內容

一個完整的HTTP請求包含:html

1.一個請求行(GET  /aa/index.html  HTTP/1.0)java

2.若干個請求頭(告訴服務器客戶端的一些信息)web

3.實體內容(請求的時候須要向服務器傳遞的內容)。瀏覽器

 

注意:請求行,請求頭,而後後空一行,請求信息(如表單提交數據爲post方式)。緩存

 

請求行:用於描述客戶端的請求方式,請求的資源名稱,以及使用的HTTP的協議版本號tomcat

GET  /aa/index.html  HTTP/1.0 服務器

 

請求頭:

告訴服務器一些客戶端的信息app

 

 

Accept:用於告訴服務器,客戶機支持的數據類型(值爲:text/html(文本),image(圖片),/*/(任何類型)webapp

Accept-Charset:客戶機採用的編碼ide

Accept-Encoding:客戶機支持的壓縮格式

Accept-Language:客戶機的語言環境,不一樣國家訪問的內容也是不一樣的,就是經過這個頭實現的,用於實現國際化

Host:告訴服務器,想訪問的主機名

If-Modified-Since:客戶機將這個頭信息發送給服務端,服務端進行比對,告訴客戶機是否去拿緩存,和服務器端返回的Last-Modified值是相等的

If-None-Match:客戶機將這個頭信息發送給服務端,服務端進行比對,告訴客戶機是否去拿緩存,和服務器端返回的Etag值是相等的

Referer:客戶機告訴服務器,他是從哪一個資源來訪問服務器的(防盜鏈),經過檢查該頭是不是從本網站點擊過來的,如不是的,就讓他跳到本網站的首頁來

User-Agen::客戶機告訴服務器,客戶機的軟件環境

Cookie:客戶機經過這個頭向服務器帶點數據

Connection:客戶機的鏈接狀態(close:關閉鏈接  Keep-Alive:不會斷開鏈接)

 

例子:

 

這個是我在訪問http://localhost:8080/aa/index.html,能夠看到請求信息。

 

以上的內容爲多個消息頭,用於描述客戶端請求哪臺主機,以及客戶端的一些環境信息等

請求行中的GET稱之爲請求方式,請求方式:post,get,head,options,delete,trace,put,經常使用的有:get,post,用戶沒有設置,默認狀況下瀏覽器向服務器發送的都是get請求,例如在瀏覽器直接輸地址訪問,點擊連接訪問都是get,用戶如想把請求方式改成post,可經過更改表單form的提交方式實現.無論post或get,都用於向服務器請求某個web資源,這兩種方式的區別主要表如今數據傳遞上:請求方式爲get方式,則能夠再請求的URL地址後以?的形式帶上交給服務器的數據,多個數據之間以&進行分割,同時在URL地址後附帶的參數是有限制的,其數據容量一般不能超過1k,若請求方式爲post方式,則能夠再請求的實體內容中向服務器發送數據,post方式的特色:傳送的數據無限制.

 

[html]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. <href="/2.html?name=jiangwei">2.html</a>  

 

點擊這個連接就是一個get方式,並且攜帶了name字段值

 

 

點擊連接是Get方式,並且是在資源地址後面攜帶信息的。

 

同時再看一下Referer這個請求頭,這個頭表明的是從當前頁面是從哪一個頁面跳轉過來的:

 

咱們點擊上面的2.html超連接,跳轉到了2.html頁面這時候能夠看到請求頭中的Referer:http://localhost:8080/aa/index.html,代表2.html頁面是從index.html頁面跳轉過來的,這個請求頭的做用仍是很大的,主要用於防盜鏈,好比用戶點擊了一個連接跳轉到一個頁面中,該頁面的網站站長髮現這個用戶不是從指定的頁面中跳轉過來的,因此就會讓頁面跳轉到該網站的首頁,讓用戶從該網站的首頁跳轉到該頁面。

 

下面在/aa/index.html文件中添加一個表單:

 

[html]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. <form action="/2.html" method="post">  
  2.     <input type="text" name="name"/>  
  3.     <input type="submit"/>  
  4. </form>  
在文本框中輸入內容,點擊提交按鈕:

 

 

能夠看到這種方式是post方式,並且在請求頭以後空一行,是請求內容信息。

 

HTTP的響應內容

響應頭:

用於描述服務器的基本信息,以及數據的描述,服務器經過這些數據的描述信息,能夠通知客戶端如何處理等一會它會送的數據

Location:這個頭配合302狀態碼使用,用於告訴用戶找誰

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. response.setStatus(302);  
  2. response.setHeader("Location","/aa/1.html");  

 

請求重定向,判斷瀏覽器的地址欄的地址是否發生變化,實例是用戶登陸

Server:服務器經過這個頭,告訴瀏覽器的類型

Content-Encoding:服務器經過這個頭,數據的壓縮格式,收費是靠數據出口量算的, 因此爲了省錢和效率高,要進行數據壓縮,jdk中的GZIPOutputStream類,壓縮類流,包裝流和底層流,最好將包裝流關了或者刷新,數據寫入到底層流中去,

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. response.setHeader("Content-Encoding","gzip");  
  2. response.setHeader("Content-length",gzip.length+"");  

 

Content-Length:服務器會送的數據的長度

Content-Type:服務器會送數據的類型,response.getOutputStream().write();服務器會送數據都是二進制,經過這個頭,能夠告訴瀏覽器這個二進制是什麼類型,

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. InputStream in = this.getServletContext().getResourceAsStream("/1.jpg");  
  2. int len = 0;  
  3. byte buffer[] =new byte[1024];  
  4. OutputStream out =response.getOutputStream();  
  5. while((len=in.read(buffer))>0){  
  6. out.write(buffer,0,len)  
  7. }  

 

在服務器的目錄下的web.xml中查看各個數據類型的respose.setHeader("content-type","")的寫法.

Refresh:告訴瀏覽器隔多長時間刷新一次,response.setHeader("refresh","3;url=""")控制瀏覽器隔三秒跳到指定的網頁上

Content-Disposition:告訴瀏覽器如下載的方式打開文件

 

[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. response.setHeader("content-disposition","attachment;filename=1.jpg);  

 

Transfer-Encoding:告訴瀏覽器數據的傳送格式

Last-Modified:服務端文件的最後修改時間,這個值返回給客戶端,客戶機第二次訪問服務器時帶來的If-Modified-Since的值和服務器的值同樣,就拿緩存給客戶,實時更新,

ETag:緩存相關的頭,服務器根據數據的內容生產一個字符串,客戶機第二次訪問服務器時帶來的If-None-Match的值和服務器的值同樣,就拿緩存給客戶,實時更新,

Expires:高速瀏覽器,把會送的資源緩存多少時間,-1或0,則是不緩存的

Pragma:no-cache

Cache-Control:no-cache

Date:控制瀏覽器不要緩存數據,當數據不發生改變時,就要緩存,當實時性要求很高的數據不能緩存.

 

響應行:

HTTP /1.1 200 OK  :狀態行,用於描述服務器對請求的處理結果

 

格式:HTTP版本號  狀態碼  緣由敘述

狀態碼用於表示服務器對請求的處理結果,他是一個三位的十進制數,響應狀態碼分爲5類,

100-199:表示接收請求,要求客戶端繼續提交下一次請求才能完成整個處理過程

200-299:表示成功接收請求並已完成整個處理過程,經常使用200

300-399:爲完成請求,客戶需進一步細化請求,例如,請求的資源已經移動一個新地址,經常使用302(你請求我,我叫你去找別人),307和304(拿緩存)

400-499:客戶端的請求有錯誤,經常使用404,403(沒有權限訪問,以前咱們在打開Tomcat Manager頁面的時候遇到過)

500-599:服務器端出現錯誤,經常使用500

 

實體內容:

在響應頭後面空一行是服務器返回的實體內容:

<HTML>

<BODY>

...........

 
下面咱們來寫一點服務端的代碼,這樣纔可以明瞭的展現各個響應頭的做用。下面就在MyEclipse中新建一個Web應用:
 
 
在工程中新建一個ServletDemo1.java來編寫服務端的代碼:代碼以下:
[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. package com.http.demo;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.OutputStream;  
  7. import java.util.zip.GZIPOutputStream;  
  8.   
  9. import javax.servlet.ServletException;  
  10. import javax.servlet.http.HttpServlet;  
  11. import javax.servlet.http.HttpServletRequest;  
  12. import javax.servlet.http.HttpServletResponse;  
  13.   
  14. public class HttpServletDemo extends HttpServlet {  
  15.   
  16.     private static final long serialVersionUID = -7234797658264000867L;  
  17.   
  18.     @Override  
  19.     protected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {  
  20.         //測試  
  21.         try{  
  22.             //test1(resp);//location響應頭  
  23.             //test2(resp);//Content-Encoding響應頭  
  24.             //test3(resp);//Content-Type響應頭  
  25.             test4(resp);//refresh響應頭  
  26.             //test5(resp);//content-disposition  
  27.         }catch(Exception e){  
  28.             e.printStackTrace();  
  29.         }  
  30.     }  
  31.   
  32.     @Override  
  33.     protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {  
  34.         doGet(req,resp);  
  35.     }  
  36.       
  37.     //使用響應頭location和302狀態碼實現請求重定向(地址欄中的地址發生改變)  
  38.     public void test1(HttpServletResponse response){  
  39.         response.setStatus(302);  
  40.         response.setHeader("Location", "/aa/3.html");  
  41.     }  
  42.       
  43.     //使用響應頭Content-Encoding實現數據的壓縮輸出  
  44.     public void test2(HttpServletResponse resp) throws Exception{  
  45.         //壓縮數據很大的時候壓縮效率纔有體現,若是數據很小的話反而更大  
  46.           
  47.         //壓縮資源:提升網頁的訪問性能,電信按照出口流量收錢的。  
  48.         String data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";//壓縮數據大點還有效果  
  49.         System.out.println("壓縮前的數據大小:"+data.length());  
  50.         ByteArrayOutputStream bout = new ByteArrayOutputStream();//底層流  
  51.         GZIPOutputStream gout = new GZIPOutputStream(bout);//包裝流通常有緩衝,沒有把緩衝區寫滿,不會寫到底層流  
  52.         gout.write(data.getBytes());  
  53.         gout.close();//等於刷新操做,將包裝流中的信息刷新  
  54.           
  55.         byte gzip[] = bout.toByteArray();//獲得壓縮後的數據  
  56.           
  57.         System.out.println("壓縮後的數據大小:"+gzip.length);  
  58.           
  59.         //通知瀏覽器數據採用壓縮格式  
  60.         resp.setHeader("Content-Encoding", "gzip");  
  61.         resp.setHeader("Content-Length", gzip.length+"");//代表長度  
  62.         resp.getOutputStream().write(gzip);//壓縮數據寫給瀏覽器  
  63.     }  
  64.       
  65.     //使用響應頭content-type設置服務器返回給client的數據類型  
  66.     public void test3(HttpServletResponse resp) throws Exception{  
  67.         //具體能夠查看tomcat目錄中的web.xml文件  
  68.         resp.setHeader("Content-Type","image/jpeg");  
  69.         InputStream ins = this.getServletContext().getResourceAsStream("/1.jpg");  
  70.         int len = 0;  
  71.         byte[] buffer = new byte[1024];  
  72.         OutputStream ops = resp.getOutputStream();  
  73.         while((len = ins.read(buffer))!=-1){  
  74.             ops.write(buffer, 0, len);  
  75.         }  
  76.         ops.close();  
  77.     }  
  78.       
  79.     //使用響應頭refresh實現頁面的定時刷新  
  80.     public void test4(HttpServletResponse resp) throws Exception{  
  81.         //股票,聊天室  
  82.           
  83.         //填充的值爲:3;url="http://www.baidu.com"表示3s以後跳轉到http://www.baidu.com頁面  
  84.         //若是沒有http://www.baidu.com的話,只是在該頁面進行刷新  
  85.         resp.setHeader("refresh", "3;url=\"http://www.baidu.com\"");  
  86.         String data = "aaaaaaaaaaaaaa";  
  87.         resp.getOutputStream().write(data.getBytes());  
  88.     }  
  89.       
  90.     //使用響應頭content-disposition實現客戶機用下載的方式打開數據資源  
  91.     public void test5(HttpServletResponse resp) throws Exception{  
  92.         resp.setHeader("content-disposition","attachment;filename=1.jpg");  
  93.         InputStream ins = this.getServletContext().getResourceAsStream("/1.jpg");  
  94.         int len = 0;  
  95.         byte[] buffer = new byte[1024];  
  96.         OutputStream ops = resp.getOutputStream();  
  97.         while((len = ins.read(buffer))!=-1){  
  98.             ops.write(buffer, 0, len);  
  99.         }  
  100.     }  
  101.       
  102. }  
 
啓動Tomcat將應用部署好,在瀏覽器中輸入:http://localhost:8080/HttpDemo/HttpServletDemo
 
第一:測試響應頭字段:Location:重定向
測試test1()方法:
 
 
在test1()方法中咱們指定了重定向的頁面是/aa/3.html,並且重定向的一個最明顯特徵就是地址欄中的地址會發生改變,這個主要用在用戶登陸的時候,當用戶登陸成功以後要重定向到指定頁面。
 
第二:測試響應頭字段:Content-Encoding:實現壓縮輸出
測試test2()方法:
 
 
咱們能夠看到壓縮輸出了,指定的是gzip壓縮輸出。這裏同時還要指定Content-Length頭字段表示返回數據的長度。同時咱們在MyEclipse中的控制檯中能夠看到:
 
壓縮以前的數據大小和壓縮以後的數據大小是4倍,這個效率很高的,這個壓縮頭字段的做用很大,對於大型的網站像新浪,搜狐這樣的門戶網站,他們的首頁很複雜的,因此這裏必需要作壓縮輸出:有兩個緣由:1.壓縮數據以後返回給客戶機很明顯可以提升該頁面的訪問性能。2.可以減小費用(壓縮數據少了,出口流量就少了,這樣運營商收費就會減小)
 
第三:響應頭字段:Content-type:告訴瀏覽器返回的數據類型
測試test3()方法:
 
 
咱們將像客戶機返回一張圖片,指定類型是imag/jpeg便可,這裏這個字段填寫的格式咱們能夠參考tomcat目錄中的web.xml文件中的全部類型的格式:
 
 
這裏就列舉了全部mime類型的書寫格式。
 
第四:測試響應頭:refresh:定時刷新
測試test4()方法:
由於又刷新的功能,這裏不能截圖了,自行演示。
這個頭字段的做用用途不少的,好比股票頁面那些數據是須要定時刷新的,還有網頁聊天室,這裏的聊天內容也是要定時刷新的。這樣咱們只須要設置這個頭便可:
[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. resp.setHeader("refresh", "3");  
每隔3s刷新該頁面
若是咱們但願頁面隔多少秒以後跳轉到指定頁面:好比咱們在網頁中認證完以後,3s以後跳轉到首頁,只須要設置以下便可:
[java]  view plain  copy
 
 在CODE上查看代碼片派生到個人代碼片
  1. resp.setHeader("refresh", "3;url=\"http://www.baidu.com\"");  
這個就是說3s以後跳轉到baidu首頁。
 
第五:測試響應頭:Content-disposition:告訴瀏覽器如下載的方式打開文件
測試test5()方法:
 
 
這裏咱們仍是使用1.jpg這張圖片,告訴瀏覽器已下載的方式打開圖片。
 
總結:上面咱們就介紹了HTTP的相關知識,關於HTTP的知識是很重要的,他是學習web的基石,因此咱們必定要搞定這裏面的全部知識,才能進行下一步的開發。
相關文章
相關標籤/搜索