JavaWeb中,HttpServletRequest與HttpServletResponse幾乎是處理各種請求與操作必備的參數,與原始的ServletRequest/ServletResponse相比,它們符合HTTP協議,所以首先從http協議入手,回顧一些基本的內容,而后根據協議來總結常用的知識點。
首先來介紹一下dos環境下簡單的http發送報文,接收報文的方法。運行輸入cmd,打開命令提示符輸入telnet 127.0.0.1 8080,回車后會出現一個輸入界面,但此時輸入的字符都無法顯示,按住‘Ctrl+]’,出現Microsoft Telnet> 再按回車,進入到該界面后,可以看到輸入的字符可以顯示。
----------------------------------------------------------------------------------------------->
http協議基本內容:
版本:1.0一次鏈接,一次請求;1.1一次鏈接,多次請求獲得不同的資源。
----------------------------------------------------------------------------------------------->
請求分為請求行,請求頭和請求體,根據請求方法的不同,可分為七種,常用的為GET, POST請求。請求行位於整個報文的第一行,包括"請求方式 資源路徑 協議",如:GET /demo/1.html?username=jack&password=1234 HTTP/1.1。請求內容會根據請求方式的不同而差異巨大,如果是GET請求,會以url拼接的形式放在請求行中資源路徑的后面,用"?"與"&"組合分割,如:http://localhost:8080/demo/1.html?username=jack&password=1234 ;如果是POST請求,則會單獨講請求內容放入請求體中。由於url的長度有限制,所以GET請求追加的內容也有限制,一般為1024字節(1k),但POST的請求體大小沒有限制。
請求頭的常用內容:
Accept: text/html,image/* --支持數據類型
Accept-Charset: ISO-8859-1 --字符集
Accept-Encoding: gzip --支持壓縮格式
Accept-Language:zh-cn --語言環境
Host: www.itheima.com:80 --訪問主機
If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT --緩存時間
Referer: http://www.itcast.com/index.jsp --來自哪個頁面、防盜鏈 – 如果沒有通過超鏈接訪問2.html返回null
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0) 用戶數據
Cookie --表示cookie技術
Connection: close/Keep-Alive --鏈接狀態
Date: Tue, 11 Jul 2000 18:23:51 GMT --時間
另外,MIME表示Multipurpose Internet Mail Extensions(多用途互聯網郵件擴展),包括以下常見內容:
格式:大類型/小類型;參數
大類型:分7類,表示互聯網所有資源。
Text:用於標准化地表示的文本信息,文本消息可以是多種字符集和或者多種格式的;
Multipart:用於連接消息體的多個部分構成一個消息,這些部分可以是不同類型的數據;
Application:用於傳輸應用程序數據或者二進制數據;
Message:用於包裝一個E-mail消息;
Image:用於傳輸靜態圖片數據;
Audio:用於傳輸音頻或者音聲數據;
Video:用於傳輸動態影像數據,可以是與音頻編輯在一起的視頻數據格式。
例如:
text/css css文件
text/html html文件
text/javascript js文件
image/* 所有圖片
image/jpeg jpg圖片
----------------------------------------------------------------------------------------------->
請求的響應也分為響應行,響應頭以及響應體。格式為:"協議/版本 狀態碼 狀態碼對應描述信息"。
狀態碼:
1xx: 服務器響應瀏覽器,數據正在發送中。一般使用很少。
2xx: 服務器響應瀏覽器已經正常結束。 常用:200 表示正常。
3xx: 服務器響應瀏覽器,請求還沒有完成,需要瀏覽器進一步操作,來完成整個請求。
常用狀態碼:
302 (307):與響應頭location 結合完成頁面重新跳轉。
304:頁面讀取緩存
4xx: 服務器響應瀏覽器,瀏覽器操作有誤。
常見:404 頁面找不到。(一般請求頁面找不到表示用戶URL寫錯)
5xx: 服務器響應瀏覽器,服務器異常
響應頭:
Location: http://www.it315.org/index.jsp --跳轉方向
Server:apache tomcat --服務器型號
Content-Encoding: gzip --數據壓縮
Content-Length: 80 --數據長度
Content-Language: zh-cn --語言環境
Content-Type: text/html; charset=GB2312 --數據類型
Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT --最后修改時間
Refresh: 1;url=http://www.it315.org --定時刷新
Content-Disposition: attachment; filename=aaa.zip --下載
Set-Cookie:SS=Q0=5Lb_nQ; path=/search
Expires: -1 --緩存
Cache-Control: no-cache --緩存
Pragma: no-cache --緩存
Connection: close/Keep-Alive --連接
Date: Tue, 11 Jul 2000 18:23:51 GMT --時間
----------------------------------------------------------------------------------------------->
以上屬於http的一些基本內容,在web服務中,兩個最常用到的參數HttpServletRequest以及HttpServletResponse都需要在深刻理解該協議的基礎上才能靈活運用。此處我們主要討論請求轉發的實現,理清重定向、頁面跳轉以及頁面刷新的過程。
重定向時,瀏覽器的請求到達服務器,服務器響應中有兩個必備的元素,一個是狀態碼:302,一個是重定向的地址,瀏覽器收到報文后,根據這兩個信息重新發送請求,到指定的Location;而頁面刷新是指,服務器在發送報文時,頭信息中包含了"refresh",使瀏覽器可以按照延時刷新本頁面或者跳轉到指定URL;請求轉發,是瀏覽器請求服務器時,服務器內部跳轉到新的URL獲取到資源並在原來的頁面展示給瀏覽器的過程,根據轉發方法的不同分為請求轉發與請求包含兩種。
兩種重定向的方式:
/** *方式一:更接近服務器響應瀏覽器的過程 */ response.setStatus(302) response.setHeader("location","http://www.changjiang.com/TestServlet"); /** *方式二:更為簡便 */ response.sendRedirect("http://www.changjiang.com/TestServlet");
頁面刷新所需要攜帶的報文內容,其實這個使用的場景也是蠻多的:
/** * 跳轉 --兩次都是200 (有可能第二個304 讀取瀏覽器緩存) * 格式:秒 --> 指定秒數刷新當前頁面 * 格式:秒;url="" --> 指定秒之后跳轉到指定的url */ response.setHeader("refresh", "2"); response.setHeader("refresh", "0;url=1.html");
來看一些用到頁面刷新的實例:
private void test1(HttpServletResponse response) throws IOException { response.setHeader("refresh", "3"); String data = new Random().nextInt(100000)+""; response.getWriter().write(data); } private void test2(HttpServletResponse response) throws IOException { response.setHeader("refresh", "3;url='/day06/index.jsp'"); response.setContentType("text/html;charset=GB2312"); response.getWriter().write("登錄成功,將在3秒后跳轉,如果沒有,請點<a href='xxx'>超鏈接</a>"); }
最后看下服務器內部進行的請求轉發,首選要獲得轉發的RequestDispatcher,
當前servlet路徑: http://localhost:8080/day08/a/b/Demo01Servlet 另一個servlet路徑:http://localhost:8080/day08/a/b/Demo02Servlet ServletRequest (常用) request.getRequestDispatcher("Demo02Servlet") request.getRequestDispatcher("/a/b/Demo02Servlet") --注意:沒有day08 , (擴展:對比重定向) ServletContext this.getServletContext().getRequestDispatcher("/a/b/Demo02Servlet ")
接着需要指定請求轉發還是請求包含:
forward(ServletRequest request, ServletResponse response) 請求轉發 A 轉發 B,只輸出B內容到瀏覽器。(如果A沒有數據發送 response.isComitted = false,將清空緩存) 請求轉發只輸出最后一個servlet內容 如果 isCommitted = true ,在進行forward將拋異常。一般情況如果輸出少量的數據,認為isCommitted=false include(ServletRequest request, ServletResponse response) 請求包含 A 包含 B,先輸出A內容到瀏覽器,在輸出B的內容到瀏覽器。 請求包含,輸出所有servlet 匯總后的內容。
在使用請求轉發時,一個request涉及到了多個servlet的資源,屬於跨域操作,需要特別注意各個資源內的編碼一致性,所以一般servlet中需要加入以下兩行代碼,保證資源編碼一致:
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
最后總結一下請求轉發的特點:
- 請求路徑沒有改變,但可以涉及服務器端多個資源
- 可以在一次請求中,共享request作用域的數據
- 一次請求,使用請求轉發,tomcat將創建兩個request和一個response對象,兩個request對象數據相同的(可以理解成對象被克隆了)