Java 中的 request 和response 理解

request和response(請求和響應)

 1.當Web容器收到客戶端的發送過來http請求,會針對每一次請求,分別建立一個用於表明這次請求的HttpServletRequest對象(request)對象、和表明響應的HTTPServletResponse對象(response)。

	request負責獲取客戶機提交過來的數據。
 response負責向客戶機輸出數據。 2.HttpServletRequest請求  GET /Servlet/servlet/Servlet_03 HTTP/1.1 Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, */* Accept-Language: zh-CN User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E) Accept-Encoding: gzip, deflate Host: localhost:8080 Connection: Keep-Alive getRequestURL方法返回客戶端發出請求時的完整URL。 getRequestURI方法返回請求行中的資源名部分。 getQueryString 方法返回請求行中的參數部分。 getRemoteAddr方法返回發出請求的客戶機的IP地址 getRemoteHost方法返回發出請求的客戶機的完整主機名 getRemotePort方法返回客戶機所使用的網絡端口號 getLocalAddr方法返回WEB服務器的IP地址。 getLocalName方法返回WEB服務器的主機名 在request中能夠獲取一些請求頭,這些請求頭的案例有: 1.能夠用來防盜鏈(Referer頭)  防盜鏈:  有些下載系統的下載地址會有一個下載跳轉,用戶在下載頁面上看到的下載地址多是 http://www.abc.com/down.asp?id=xxxx     有人直接將這個地址複製到其餘地方,便可盜鏈,直接利用下載的地址就能夠實現下載,而不是經過我本身的網站去下載,這時咱們就須要判斷下是不是經過我本身的網站點擊下載的。 因此咱們須要在 down.asp 這個頁面作下簡單的來源判斷。若是不是來自本站的鏈接,則直接拒絕訪問。  String referer = request.getHeader("referer");//獲取請求頭           //判斷這個頭是否爲空,或這個頭的首地址是否爲http://localhost,若是不是則重定向  2.獲取表單中的信息:  String value = req.getParameter("name");  在表單提交過來時的中文亂碼的問題:   *瀏覽器怎樣進行URL編碼:  (1)瀏覽器對FORM表單中輸入的中文字符都會進行URL編碼後再傳送給WEB服務器。  (2)對於頁面中的FORM表單中輸入的內容,瀏覽器將按照當前顯示頁面時所採用的字符集編碼來進行URL編碼。  getParameter方法的中文問題:  (1)getParameter等方法在讀取的參數信息時,須要進行URL解碼。  (2)對於HTTP請求消息的請求行中的URL地址後的參數,getParameter等方法進行URL解碼時所採用的字符集編碼在Servlet規範中沒有明確規定Tomcat中的ServletReq uest對象的getParameter等方法默認採用ISO8859-1字符集編碼進行URL解碼,所以沒法返回正確的中文參數信息 。  (3)對於POST方式下的「application/x-www-form-urlencoded」編碼格式的實體內容,getParameter等方法以ServletRequest對象的getCharacterEncoding()方法返 回的字符集編碼對其進行URL解碼。  (4)getCharacterEncoding()方法的返回值一般爲null,對於這種狀況,ServletRequest對象的getParameter等方法將使用默認的ISO8859-1字符集編碼對實體內容中 的參數進行URL解碼,所以也將沒法返回正確的中文參數信息。  (5)ServletRequest接口中定義了一個setCharacterEncoding方法來設置請求消息中的實體內容的字符集編碼名稱,getParameter方法將以該方法設置的字符集編碼 對實體內容進行URL解碼。  (6)setCharacterEncoding方法設置的是請求消息中的實體內容的字符集編碼名稱,它隻影響getParameter方法對POST方式下的「application/x-www-form-urlencod ed」編碼格式的實體內容進行URL解碼的結果,而不能影響getParameter方法對HTTP請求消息的請求行中的URL地址後的參數進行URL解碼的結果。
	解決方案:
	1.post方式
		對於POST方式,表單中的參數值對是經過request包發送給服務器,此時瀏覽器會根據網頁的ContentType("text/html; charset=GBK")中指定的編碼進行對錶單中的數據進行編碼,而後發給服務器。
在服務器中根據:request.setCharacterEncoding(""),只要編碼跟瀏覽器一直的就能夠。
	2.get方式
對於GET方式,咱們知道它的提交是將請求數據附加到URL後面做爲參數,這樣依賴亂碼就會很容易出現,由於數據name和value頗有可能就是傳遞的爲非ASCII碼。

當URL拼接後,瀏覽器對其進行encode,而後發送到服務器。具體規則見URL編碼規則。

這裏詳細說一下encode的過程當中容易出現的問題,在這個過程當中咱們要明白鬚要URL encode的字符通常都是非ASCII碼字符,因此咱們就能知道出現亂碼主要是URL中附加了中文或特殊字符作成的,另外一個要知道URL encode究竟是以什麼樣的編碼方式對字符進行編碼的,其實這個編碼方式是由瀏覽器決定的,不一樣的瀏覽器和同一瀏覽器的不一樣設置影響了URL的編碼,因此爲了不咱們不須要的編碼,咱們能夠經過java代碼或javaspcript代碼統一進行控制。

完成了URL encode以後URL就成了ASCII範圍內的字符了,而後就以iso-8859-1的編碼方式轉換爲二進制隨着請求頭一塊兒發送出去。

到了服務器以後,首先服務器會先用iso-8859-1進行解碼,服務器獲取的數據都是ASCII範圍內的請求頭字符,其中請求URL裏面帶有參數數據,若是是中衛或特殊字符,那麼encode後的%XY(編碼規則中的十六進制數)經過request.setCharacterEncoding()是無論用的。這時候咱們就能發現出現亂碼的根本緣由就是客戶端通常是經過用UTF-8或GBK等對數據進行encode的,到了服務器卻用iso-8859-1方式decoder顯然不行。
		String value = new String(req.getParameter("name").getBytes("iso-8859-1"),"GBK");
3.request對象實現請求轉發:
 RequestDispatcher requestDispatcher = req.getRequestDispatcher("/index.jsp");  requestDispatcher.forward(req, resp); 請求重定向和請求轉發:是Servlet處理完數據後進行頁面跳轉的兩種主要方式  請求轉發:  請求轉發是指將請求再轉發到另外一資源(通常爲JSP或Servlet)。此過程依然在同一個請求範圍內,轉發後瀏覽器地址欄內 容不變  請求轉發使用RequestDispatcher接口中的forward()方法來實現,該方法能夠把請求轉發到另一個資源,並讓該資源對瀏 覽器的請求進行響應  請求重定向:  重定向是指頁面從新定位到某個新地址,以前的請求失效,進入一個新的請求,且跳轉後瀏覽器地址欄內容將變爲新的指定 地址    重定向是經過HttpServletResponse對象的sendRedirect()來實現,該方法至關於瀏覽器從新發送一個請求  //1.請求轉發  RequestDispatcher requestDispatcher = req.getRequestDispatcher("/index.jsp");  requestDispatcher.forward(req, resp);   //2.請求重定向:  resp.sendRedirect("http://localhost:8080/Servlet/servlet/Servlet_03"); 區別: 1.使用請求重定向,瀏覽器會向服務器發送兩次請求,而請求轉發則爲一次請求
2.地址欄顯示不同請求轉發地址欄沒有變化,而請求重定向地址欄會顯示新的請求地址

HttpServletResponse.sendRedirect方法和RequestDispatcher.forward方法的區別:
儘管HttpServletResponse.sendRedirect方法和RequestDispatcher.forward方法均可以讓瀏覽器得到另一個URL所指向的資源,但
二者的內部運行機制有着很大的區別。下面是HttpServletResponse.sendRedirect方法實現的請求重定向與

RequestDispatcher.forward方法實現的請求轉發的總結比較:
(1)RequestDispatcher.forward方法只能將請求轉發給同一個WEB應用中的組件;而HttpServletResponse.sendRedirect 方法不只
能夠重定向到當前應用程序中的其餘資源,還能夠重定向到同一個站點上的其餘應用程序中的資源,甚至是使用絕對URL重定向到其
他站點的資源。若是傳遞給HttpServletResponse.sendRedirect 方法的相對URL以「/」開頭,它是相對於整個WEB站點的根目錄;如
果建立RequestDispatcher對象時指定的相對URL以「/」開頭,它是相對於當前WEB應用程序的根目錄。
(2)調用HttpServletResponse.sendRedirect方法重定向的訪問過程結束後,瀏覽器地址欄中顯示的URL會發生改變,由初始的URL
地址變成重定向的目標URL;而調用RequestDispatcher.forward 方法的請求轉發過程結束後,瀏覽器地址欄保持初始的URL地址不變
。
(3)HttpServletResponse.sendRedirect方法對瀏覽器的請求直接做出響應,響應的結果就是告訴瀏覽器去從新發出對另一個URL
的 訪問請求,這個過程比如有個綽號叫「瀏覽器」的人寫信找張三借錢,張三回信說沒有錢,讓「瀏覽器」去找李四借,並將李四
如今的通訊地址告訴給了「瀏覽器」。因而,「瀏覽器」又按張三提供通訊地址給李四寫信借錢,李四收到信後就把錢匯給了「瀏覽
器」。可見,「瀏覽器」一共發出了兩封信和收到了兩次回覆, 「瀏覽器」也知道他借到的錢出自李四之手。
RequestDispatcher.forward方 法在服務器端內部將請求轉發給另一個資源,瀏覽器只知道發出了請求並獲得了響應結果,並不知
道在服務器程序內部發生了轉發行爲。這個過程比如綽號叫「瀏覽器」的人寫信找張三借錢,張三沒有錢,因而張三找李四借了一些
錢,甚至還能夠加上本身的一些錢,而後再將這些錢匯給了「瀏覽器」。可見,「瀏覽器」只發 出了一封信和收到了一次回覆,他
只知道從張三那裏借到了錢,並不知道有一部分錢出自李四之手。
(4)RequestDispatcher.forward方法的調用者與被調用者之間共享相同的request對象和response對象,它們屬於同一個訪問請求
和響應過程;而HttpServletResponse.sendRedirect方法調用者與被調用者使用各自的request對象和response對象,它們屬於兩個
獨立的訪問請求和響應過程。對於同一個WEB應用程序的內部資源之間的跳轉,特別是跳轉以前要對請求進行一些前期預處理,並要
使用HttpServletRequest.setAttribute方法傳遞預處理結果,那就應該使用RequestDispatcher.forward方法。不一樣WEB應用程序之
間的重定向,特別是要重定向到另一個WEB站點上的資源的狀況,都應該使用HttpServletResponse.sendRedirect方法。
(5)不管是RequestDispatcher.forward方法,仍是HttpServletResponse.sendRedirect方法,在調用它們以前,都不能有內容已經
被實際輸出到了客戶端。若是緩衝區中已經有了一些內容,這些內容將被從緩衝區中清除。
場景應用:
 請求轉發:  用於不一樣應用場景 通常來說,在MVC設計模式下,一個servlet將數據交給jsp來作顯示就使用請求轉發,由於不必讓用戶 知道內部實現原理,同時對jsp頁面也能夠作保護  重定向:  用戶登陸成功跳轉到首頁面是用請求重定向,由於此時須要讓用戶明確知道本身登陸成功並跳轉到了首頁 include和forward的區別: forward會轉發到相應的資源中。 而include會將包含的資源處理下,以後在處理本身的頁面。 
例子:
[java] view plain copy
  1. package com.enterise.always.servlet;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.RequestDispatcher;  
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.http.HttpServlet;  
  8. import javax.servlet.http.HttpServletRequest;  
  9. import javax.servlet.http.HttpServletResponse;  
  10. import javax.servlet.http.HttpSession;  
  11.   
  12. public class Servlet_05 extends HttpServlet{  
  13.     private static final long serialVersionUID = 1L;  
  14.   
  15.     protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
  16.             throws ServletException, IOException {  
  17.         this.doPost(req, resp);  
  18.     }  
  19.   
  20.     protected void doPost(HttpServletRequest req, HttpServletResponse resp)  
  21.             throws ServletException, IOException {  
  22.         //1.請求轉發  
  23. //      RequestDispatcher requestDispatcher = req.getRequestDispatcher("/index.jsp");  
  24. //      requestDispatcher.forward(req, resp);  
  25. //      requestDispatcher.include(req, resp);  
  26.           
  27.         //2.請求重定向:  
  28. //      resp.sendRedirect("http://localhost:8080/Servlet/servlet/Servlet_03");  
  29.           
  30.         //3.include和forward的區別  
  31.           
  32.         RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet/Servlet_03");  
  33.         requestDispatcher.forward(req, resp);  
  34. //      requestDispatcher.include(req, resp);  
  35.           
  36.         resp.getOutputStream().write("Servlet_05".getBytes());  
  37.           
  38.           
  39.     }  
  40. }  
include的結果爲:servlet_03Servlet_05
forward的結果爲:servlet_03

2.HttpServletResponse
 	HttpServletResponse對象表明服務器的響應。這個對象中封裝了向客戶端發送數據、發送響應頭,發送響應狀態碼的方法。
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Length: 0
Date: Tue, 03 Sep 2013 03:52:13 GMT

1.getOutputStream和getWriter方法分別用於獲得輸出二進制數據、輸出文本數據的ServletOuputStream、Printwriter對象。
可是兩則不能結合在一塊兒使用,緣由是:
兩個對象的流不同:
getOutputStream:方法用於返回Servlet引擎建立的字節輸出流對象
getWriter:返回Servlet引擎建立的字符輸出流對象
這兩個方法互斥,調用了其中的一個方法以後,就不能在調用另一個。

Serlvet的service方法結束後,Servlet引擎將檢查getWriter或getOutputStream方法返回的輸出流對象是否已經調用過close方法,

若是沒有,Servlet引擎將調用close方法關閉該輸出流對象。

response的其餘功能:
經過setStats方法能夠設置響應頭的狀態碼
經過setHead方法能夠設置響應頭
常見應用

發送REFRESH頭,控制瀏覽器定時刷新網頁
發送Expires頭,控制瀏覽器禁止緩存當前文檔內容 

發送content-type頭通知瀏覽器打開文件的方式
response.setCharacterEncoding("GBK");
//設置瀏覽器定時刷新
response.setHeader("refresh", "3");
response.getWriter().write("定時刷新中");


//設置瀏覽器禁止緩存
response.setDateHeader("Expires", 0);  
        response.setHeader("Cache-Control", "no-cache");  
        response.setHeader("Prama", "no-cache"); 


//實現文件的下載
//對於中文文件名,若是想正常,必定要通過url編碼
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(filename,


"UTF-8"));
[java] view plain copy
  1. package com.enterise.always.servlet;  
  2.   
  3.   
  4. import java.io.FileInputStream;  
  5. import java.io.IOException;  
  6. import java.io.OutputStream;  
  7. import java.net.URLEncoder;  
  8.   
  9.   
  10. import javax.servlet.ServletException;  
  11. import javax.servlet.http.HttpServlet;  
  12. import javax.servlet.http.HttpServletRequest;  
  13. import javax.servlet.http.HttpServletResponse;  
  14.   
  15.   
  16. public class Servlet_06 extends HttpServlet{  
  17.     private static final long serialVersionUID = 1L;  
  18.   
  19.   
  20.     protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
  21.             throws ServletException, IOException {  
  22.         this.doPost(req, resp);  
  23.     }  
  24.   
  25.   
  26.     protected void doPost(HttpServletRequest req, HttpServletResponse response)  
  27.             throws ServletException, IOException {  
  28.         //獲取到下載資源的絕對路徑getRealPath("e://aa/aa.jpg");  
  29.         String path = "e://aa/aa.jpg";  
  30.         String filename = path.substring(path.lastIndexOf("\\")+1);  
  31.           
  32.         //對於中文文件名,若是想正常,必定要通過url編碼  
  33.         response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));  
  34.           
  35.         FileInputStream in = new FileInputStream(path);  
  36.         OutputStream out = response.getOutputStream();  
  37.         try {  
  38.             int len = 0;  
  39.             byte buffer[] = new byte[1024];  
  40.             while ((len = in.read(buffer)) > 0) {  
  41.                 out.write(buffer, 0, len);  
  42.             }  
  43.         } finally {  
  44.             if (in != null)  
  45.                 try {  
  46.                     in.close();  
  47.                 } catch (Exception e) {  
  48.                 }  
  49.             ;  
  50.             if (out != null)  
  51.                 try {  
  52.                     out.close();  
  53.                 } catch (Exception e) {  
  54.                 }  
  55.             ;  
  56.         }  
  57.           
  58.     }  
  59.   
  60.   
  61.       
  62.       
  63. }  
302狀態碼和location頭便可實現重定向


response.setStatus(302);
response.setHeader("location","/Servlet/index.jsp");
相關文章
相關標籤/搜索