Java HttpServletRequest中getAttribute()方法和getParameter()區別


  一、ServletRequest接口

  HttpServletRequest接口繼承了ServletRequest接口,實現類通常代表一個實際的Http Request。

  Servlet容器負責創建一個HttpServletRequest對象(在Web服務器接收到瀏覽器的一個請求后),然后Servlet容器把這個HttpServletRequest傳遞給相關Servlet的service方法。(其實同時創建和傳遞的還有HttpServletResponse對象,這也是我們在編寫相關Servlet時,無須關注request是如何被接收,也無須關注response最終如何被返回,這些都是Servlet容器和Web服務器的職責)

 

  ServletRequest接口,定義了一個能代表實際request的對象,它包含了這個request的各項信息。

  一個ServletRequest對象提供的數據包括了parameter name and value,attributes,以及input stream。HttpServletRequest對象還能提供額外的http協議相關的信息(他是唯一的子接口)。

  當然接口只是定義了行為規范,Java為其提供了兩個基礎的實現,以供開發人員擴展:

  HttpServletRequestWrapper, ServletRequestWrapper。

 

  二、Request中的parameter 和 attributes

  2.1 首先來個大體的區分

  Request parameter是客戶端提交過來的參數,以“name=value”的字符串形式存儲在Request對象中,所以對於parameter,只有getParameter方法。

  例如,我們登錄時提交賬戶信息,假如是GET方法提交(實際上不會用GET提交),那么在提交的信息會以"?username=root&password=123456"這種形式附加在表單指向的url后面,這種形式稱之為Query String。而POST方式則會把信息放在Request Body當中,這種形式稱之為POST Body。

  StackOverFlow

  一個有意思的點是,Query string data is presented(顯示) BEFORE post body data. 

  例如,如果使用Query String提交“a=hello”和POST Body提交“a=goodbye“和”a=world”,則結果參數集將被排序為a=(hello, goodbye, world)。

 

  更新:發現我以前講得不夠清楚。可以參考下列網址:

  How are parameters sent in an HTTP POST request?

  HTTP中application/x-www-form-urlencoded字符說明

  四種常見的 POST 提交數據方式

 

  在將post表單數據填充到參數集(parameter set)之前,必須滿足以下條件:

  • The request is an HTTP or HTTPS request.
  • The HTTP method is POST.
  • The content type is application/x-www-form-urlencoded.
  • The servlet has made an initial call of any of the 'getParameter' family of methods on the request object.

  如果不滿足條件,且post表單數據不包含在參數集中,post數據仍然可以通過request object的輸入流提供給servlet。

  如果滿足這些條件,post表單數據將不再可以直接從請求對象的輸入流中讀取。

 

   Request attributes則與客戶端無關,服務器端接收后產生的一個Request對象,可能在各個不同的Servlet間傳遞而進行必要的處理,這時我們可以在Servlet A中通過setAttribute(String name,Object)方法存儲一些信息,然后在Servlet B中通過getAttribute(String name)方法,取出相關的Object對象,進行一些處理。

  API中提到了一點,Attributes are reset between requests,我有點疑惑為什么要特意提這樣一句,直觀上來說,在不同的Request對象上存儲東西,二者當然不會共享吧?所以對Attributes的存儲機制開始好奇了。

  An attribute is a server variable that exists within a specified scope i.e.:

 

  • application, available for the life of the entire application
  • session, available for the life of the session
  • request, only available for the life of the request
  • page (JSP only), available for the current JSP page only

 

  可以確定的一點是,當代碼中出現了setAttribute()方法時,那么這個Request對象必定會與一個RequestDispatcher對象一起工作了,因為你在此處添加了一些有用的數據,肯定要在別處取出來用吧?

  2.2 RequestDispatcher接口

  先總結,RequestDispatcher接口類用於request的轉發。

  RequestDispatcher也是一個接口,它定義一個這樣的對象:接收來自客戶端的request,然后把他們送到服務器的其他資源上去(如servlet,html文件,JSP文件)。所以,通常是Servlet容器創建RequestDispatcher對象,用於包裝一個有特定路徑或者名稱的服務器端資源。

  這個接口用於包裝servlet,但是servlet容器可以創建RequestDispatcher對象來包裝任何類型的資源。

  在JDK中,這個接口沒有任何子接口和實現類。但是在ServletContext接口(Defines a set of methods that a servlet uses to communicate with its servlet container)中有幾個get方法來獲得RequestDispatcher對象。

 

  RequestDispatcher接口,也僅有兩個方法:

  void forward(ServletRequest request, ServletResponse response),把一個request從一個Servlet中轉發到服務端的另一處資源(servlet, JSP file, or HTML file)。

  該方法允許一個servlet對請求進行初步處理,並允許另一個資源生成響應。

  對於通過getRequestDispatcher()獲得的RequestDispatcher, ServletRequest對象調整了其路徑元素和參數,以匹配目標資源的路徑。

  forward()方法,應該在將response提交給客戶機之前(在response body output被刷新之前)調用。如果response已經被提交了,調用forward()會拋出IllegalStateException。 response緩沖區中未提交的輸出,在forward()調用前,會自動被清除。(Uncommitted output in the response buffer is automatically cleared before the forward.)

  傳遞給forward的兩個對象,要和servlet中service方法中獲得的對象是相同的。即針對的是同一次請求過程。

 

  void include(ServletRequest request, ServletResponse response),這個方法用於向response中添加一些資源(servlet, JSP page, HTML file)。

  這里就涉及到ServletResponse對象了,它代表着一個要被返回的Response。ServletResponse對象也由Servlet容器創建,(在這樣的一個轉發過程中)它的路徑元素和參數與調用者的保持不變(The ServletResponse object has its path elements and parameters remain unchanged from the caller's. )而且進行include操作的servlet,無法改變response的狀態碼,也無法設置header信息,這樣的操作會被無視掉。(why?)

  這里 include方法的ServletRequest request和ServletResponse response必須與傳遞給調用該include方法的servlet的service方法的兩個ServletRequest request和ServletResponse response是同一對(反正一般也不會自己創建了),或者是包裝前面這兩個對象的ServletRequestWrapper或ServletResponseWrapper類的子類。

 

  三、ServletResponse接口

  3.1 

  HttpServletResponse接口的父接口,定義一個對象來幫助servlet向客戶端發送response。

  Servlet容器會創建一個 ServletResponse對象,然后與ServletRequest一起傳遞給servlet的service方法。

  如果要在MIME body response中發送二進制數據,請使用getOutputStream()返回的ServletOutputStream。(什么是MIME)

  要發送字符數據,使用getWriter()返回的PrintWriter對象。

  要混合二進制和文本數據,例如,創建一個multipart響應,請使用ServletOutputStream並手動管理字符部分。

  MIME主體響應的字符集可以使用以下任何一種技術顯式指定:

 per request, per web-app (using ServletContext.setRequestCharacterEncoding(java.lang.String), deployment descriptor(即web.xml)), and per container (for all web applications deployed in that container, using vendor specific configuration(更改web容器的配置)).

  如果使用了前面提到的多種技術,那么優先級就是所列的順序。

  對於每個請求,可以使用本接口中的setCharacterEncoding(java.lang.String)和setContentType(java.lang.String)方法顯式地指定響應的字符集,或者隱式地使用setLocale(java.util.Locale)方法 。

  顯式規范優先於隱式規范。如果沒有明確指定字符集,將使用ISO-8859-1。

  setCharacterEncoding、setContentType或setLocale方法的調用必須在getWriter之前,並在提交要使用的字符編碼的響應之前

  3.2 方法

  ServletResponse接口定義的方法並不復雜,都和設置response的相關的格式有關,其中的一些會設置reponse header。

 

  四、再談談ServletContext接口

  前面已經提到過了,ServletContext中定義了一系列方法讓servlet與servlet容器打交道,例如獲取文件的MIME類型、分派request或寫入日志文件。

  每個Java虛擬機中的每個“web應用程序”,都有一個上下文(context)。

  而一個“Web Application”的定義:

  A "web application" is a collection of servlets and content installed under a specific subset of the server's URL namespace, such as /catalog and possibly installed via a .war file.)

  對於在部署描述符中標記為“distributed”的web應用程序,每個虛擬機都有一個上下文實例。在這種情況下,上下文不能用作共享全局信息的位置(因為信息不是真正的全局的)。使用外部資源,比如數據庫。

  ServletContext對象包含在ServletConfig對象中,這個對象用於Web服務器在初始化servlet時提供給servlet。API鏈接

  ServletContext提供的方法,與我們在web.xml中常進行的一些配置相似。如添加Filter、Listener、Servlet等。

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM