1. 程式人生 > >Java HttpServletRequest中getAttribute()方法和getParameter()區別

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 首先來個大體的區分

  parameter是客戶端提交過來的引數,以“name=value”的字串形式儲存在Request物件中。例如,我們登入時提交賬戶資訊,假如是GET方法提交(實際上不會用GET提交),那麼在提交的資訊會以"?username=root&password=123456"這種形式附加在表單指向的url後面。而POST方式則會把資訊放在Request Body當中。所以對於parameter,只有getParameter方法。

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

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

  可以確定的一點是,當代碼中出現了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等。