- 輕量級Java EE企業應用開發實戰
- 柳偉衛編著
- 1679字
- 2022-07-29 14:31:19
3.4 請求
請求對象封裝了客戶端請求的所有信息。在HTTP協議中,這些信息包含在從客戶端發送到服務器請求的HTTP頭部和消息體中。
3.4.1 HTTP協議參數
Servlet的請求參數以字符串的形式作為請求的一部分從客戶端發送到Servlet容器。當請求是一個HttpServletRequest對象且符合“參數可用時”描述的條件時,容器從URI查詢字符串和POST數據中填充參數。參數以一系列的名-值對(name-value)的形式保存。任何給定的參數的名稱可存在多個參數值。ServletRequest接口的以下方法可訪問這些參數:
- getParameter
- getParameterNames
- getParameterValues
- getParameterMap
getParameterValues方法返回一個String對象的數組,包含了與參數名稱相關的所有參數值。
getParameter方法的返回值必須是getParameterValues方法返回的String對象數組中的第一個值。
getParameterMap方法返回請求參數的一個java.util.Map對象,其中以參數名稱作為Map鍵,參數值作為Map值。
查詢字符串和POST請求的數據被匯總到請求參數集合中。查詢字符串數據放在POST數據之前。例如,請求由查詢字符串a=hello和POST數據a=goodbye&a=world組成,得到的參數集合順序將是a=(hello, goodbye, world)。
這些API不會暴露GET請求(HTTP 1.1所定義的)的路徑參數。它們必須從getRequestURI方法或getPathInfo方法返回的字符串值中解析。
post表單數據填充到參數集(Parameter Set)前必須滿足以下條件:
- 該請求是一個HTTP或HTTPS請求。
- HTTP方法是POST。
- 內容類型是application/x-www-form-urlencoded。
- 該Servlet已經對請求對象的任意getParameter方法進行了初始調用。
如果不滿足這些條件,而且參數集中不包括post表單數據,那么Servlet必須可以通過請求對象的輸入流得到post數據。如果滿足這些條件,那么從請求對象的輸入流中直接讀取post數據將不再有效。
3.4.2 屬性
屬性是與請求相關聯的對象。屬性可以由容器設置來表達信息,否則無法通過API表示,或者由Servlet設置將信息傳達給另一個Servlet(通過RequestDispatcher)。屬性通過ServletRequest接口中的以下方法來訪問:
- getAttribute
- getAttributeNames
- setAttribute
一個屬性名稱只能關聯一個屬性值。
3.4.3 請求頭
通過下面的HttpServletRequest接口方法,Servlet可以訪問HTTP請求的頭信息:
- getHeader
- getHeaders
- getHeaderNames
getHeader方法返回給定頭名稱的頭。多個頭可以具有相同的名稱,例如HTTP請求中的Cache-Control頭。如果多個頭的名稱相同,getHeader方法就返回請求中的第一個頭。getHeaders方法允許訪問所有與特定頭名稱相關的頭值,返回一個String對象的Enumeration(枚舉)。
頭可包含String形式的Int或Date數據。HttpServletRequest接口提供如下方法訪問這些類型的頭數據:
- getIntHeader
- getDateHeader
如果getIntHeader方法不能轉換為Int的頭值,就拋出NumberFormatException異常。如果getDateHeader方法不能把頭轉換成一個Date對象,就拋出IllegalArgumentException異常。
3.4.4 請求路徑元素
引導Servlet服務請求的請求路徑由許多重要部分組成:
URI = Context Path + Servlet Path + PathInfo
其中:
- Context Path:與ServletContext相關聯的路徑前綴是這個Servlet的一部分。如果這個上下文是基于Web服務器的URL命名空間的“默認”上下文,那么這個路徑將是一個空字符串。否則,如果上下文不是基于服務器的命名空間,那么這個路徑以“/”字符開始,但不以“/”字符結束。
- Servlet Path:路徑部分直接與激活請求的映射對應。這個路徑以“/”字符開頭,如果請求與“/*”或“”模式匹配,在這種情況下,它是一個空字符串。
- PathInfo:請求路徑的一部分,不屬于Context Path或Servlet Path。如果沒有額外的路徑,它要么是null,要么是以“/”開頭的字符串。使用HttpServletRequest接口中的以下方法來訪問這些信息:
getContextPath
getServletPath
getPathInfo
表3-1展示了請求路徑元素的使用例子。
表3-1 請求路徑元素的使用例子

3.4.5 路徑轉換方法
在Servlet API中有兩個方便的方法,允許開發者獲得與某個特定的路徑等價的文件系統路徑。這兩個方法是:
- ServletContext.getRealPath
- HttpServletRequest.getPathTranslated
getRealPath方法需要一個String參數,并返回一個String形式的路徑,這個路徑對應一個在本地文件系統上的文件。getPathTranslated方法推斷出請求的pathInfo的實際路徑。
這些方法在Servlet容器無法確定一個有效的文件路徑的情況下返回null,比如Web應用程序不能訪問遠程文件系統上的本地文件。JAR文件中META-INF/resources目錄下的資源只有當調用getRealPath()方法時才認為容器已經從包含它的JAR文件中解壓,在這種情況下必須返回解壓縮后的位置。
3.4.6 請求數據編碼
目前,很多HTTP請求并不一定會在Content-Type頭上設置字符編碼限定符。如果客戶端請求沒有指定請求默認的字符編碼,那么容器用來創建請求讀取器和解析POST數據的編碼必須是ISO-8859-1。
如果客戶端沒有設置字符編碼,并使用不同的編碼來編碼請求數據,而不是使用上面描述的默認的字符編碼,那么可能會發生問題。為了彌補這種情況,開發人員可以通過下面幾種方法來覆蓋由容器提供的字符編碼:
- *ServletContext上提供了setRequestCharacterEncoding(String enc)。
- web.xml中提供了元素。
- ServletRequest接口上提供了setCharacterEncoding(String enc)。
必須在解析任何post數據或從請求讀取任何輸入之前調用上述方法。上述方法一旦調用,將不會影響已經讀取的數據的編碼。