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文件中添加內容:

<img src="1.jpg"/>
<img src="2.jpg"/>
<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方式的特色:傳送的數據無限制.

<a 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文件中添加一個表單:

<form action="/2.html" method="post">
	<input type="text" name="name"/>
	<input type="submit"/>
</form>
在文本框中輸入內容,點擊提交按鈕:



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


HTTP的響應內容

響應頭:

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

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

response.setStatus(302);
response.setHeader("Location","/aa/1.html");

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

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

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

response.setHeader("Content-Encoding","gzip");
response.setHeader("Content-length",gzip.length+"");

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

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

InputStream in = this.getServletContext().getResourceAsStream("/1.jpg");
int len = 0;
byte buffer[] =new byte[1024];
OutputStream out =response.getOutputStream();
while((len=in.read(buffer))>0){
out.write(buffer,0,len)
}

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

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

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

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來編寫服務端的代碼:代碼以下:
package com.http.demo;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HttpServletDemo extends HttpServlet {

	private static final long serialVersionUID = -7234797658264000867L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
		//測試
		try{
			//test1(resp);//location響應頭
			//test2(resp);//Content-Encoding響應頭
			//test3(resp);//Content-Type響應頭
			test4(resp);//refresh響應頭
			//test5(resp);//content-disposition
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
		doGet(req,resp);
	}
	
	//使用響應頭location和302狀態碼實現請求重定向(地址欄中的地址發生改變)
	public void test1(HttpServletResponse response){
		response.setStatus(302);
		response.setHeader("Location", "/aa/3.html");
	}
	
	//使用響應頭Content-Encoding實現數據的壓縮輸出
	public void test2(HttpServletResponse resp) throws Exception{
		//壓縮數據很大的時候壓縮效率纔有體現,若是數據很小的話反而更大
		
		//壓縮資源:提升網頁的訪問性能,電信按照出口流量收錢的。
		String data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";//壓縮數據大點還有效果
		System.out.println("壓縮前的數據大小:"+data.length());
		ByteArrayOutputStream bout = new ByteArrayOutputStream();//底層流
		GZIPOutputStream gout = new GZIPOutputStream(bout);//包裝流通常有緩衝,沒有把緩衝區寫滿,不會寫到底層流
		gout.write(data.getBytes());
		gout.close();//等於刷新操做,將包裝流中的信息刷新
		
		byte gzip[] = bout.toByteArray();//獲得壓縮後的數據
		
		System.out.println("壓縮後的數據大小:"+gzip.length);
		
		//通知瀏覽器數據採用壓縮格式
		resp.setHeader("Content-Encoding", "gzip");
		resp.setHeader("Content-Length", gzip.length+"");//代表長度
		resp.getOutputStream().write(gzip);//壓縮數據寫給瀏覽器
	}
	
	//使用響應頭content-type設置服務器返回給client的數據類型
	public void test3(HttpServletResponse resp) throws Exception{
		//具體能夠查看tomcat目錄中的web.xml文件
		resp.setHeader("Content-Type","image/jpeg");
		InputStream ins = this.getServletContext().getResourceAsStream("/1.jpg");
		int len = 0;
		byte[] buffer = new byte[1024];
		OutputStream ops = resp.getOutputStream();
		while((len = ins.read(buffer))!=-1){
			ops.write(buffer, 0, len);
		}
		ops.close();
	}
	
	//使用響應頭refresh實現頁面的定時刷新
	public void test4(HttpServletResponse resp) throws Exception{
		//股票,聊天室
		
		//填充的值爲:3;url="http://www.baidu.com"表示3s以後跳轉到http://www.baidu.com頁面
		//若是沒有http://www.baidu.com的話,只是在該頁面進行刷新
		resp.setHeader("refresh", "3;url=\"http://www.baidu.com\"");
		String data = "aaaaaaaaaaaaaa";
		resp.getOutputStream().write(data.getBytes());
	}
	
	//使用響應頭content-disposition實現客戶機用下載的方式打開數據資源
	public void test5(HttpServletResponse resp) throws Exception{
		resp.setHeader("content-disposition","attachment;filename=1.jpg");
		InputStream ins = this.getServletContext().getResourceAsStream("/1.jpg");
		int len = 0;
		byte[] buffer = new byte[1024];
		OutputStream ops = resp.getOutputStream();
		while((len = ins.read(buffer))!=-1){
			ops.write(buffer, 0, len);
		}
	}
	
}


啓動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()方法:
由於又刷新的功能,這裏不能截圖了,自行演示。
這個頭字段的做用用途不少的,好比股票頁面那些數據是須要定時刷新的,還有網頁聊天室,這裏的聊天內容也是要定時刷新的。這樣咱們只須要設置這個頭便可:
resp.setHeader("refresh", "3");
每隔3s刷新該頁面
若是咱們但願頁面隔多少秒以後跳轉到指定頁面:好比咱們在網頁中認證完以後,3s以後跳轉到首頁,只須要設置以下便可:
resp.setHeader("refresh", "3;url=\"http://www.baidu.com\"");
這個就是說3s以後跳轉到baidu首頁。

第五:測試響應頭:Content-disposition:告訴瀏覽器如下載的方式打開文件
測試test5()方法:



這裏咱們仍是使用1.jpg這張圖片,告訴瀏覽器已下載的方式打開圖片。

總結:上面咱們就介紹了HTTP的相關知識,關於HTTP的知識是很重要的,他是學習web的基石,因此咱們必定要搞定這裏面的全部知識,才能進行下一步的開發。
相關文章
相關標籤/搜索