第四章
4 requeset
request對象包含了客戶端的所有請求信息。在HTTP協議中,客戶端發送到服務端的信息都包
含在請求的HTTP 頭和消息體中
4.1 HTTP 協議的參數
客戶端發送給servlet引擎的參數是包含在請求中的,引擎從客戶端請求的URI字符串中或POST數據中解
析出請求的參數。參數以name-value的形式存儲的。任何一個name可以對應多個value。在
ServletRequest接口的方法中:
getParameter
getParameterNames
getParameterValues
getParameterValues方法返回關聯到一個name上的一個String對象的數組。getParameter返回name對
應的values數組中的第一個value。URI和POST體中的參數都會放入請求參數的set對象中。URI中的參
數會在POST體之前被引入,如URI中的參數“a=hello”post體中的參數是a=goodbye&a=world,則參數set
中的內容是a=(hello,goodbye,world).以HTTP GET請求的參數是不隱蔽的,參數必須通過
getRequestURI或getPathInfo方法獲得參數字串。
4.1.1 參數什么時候有效
在post form中的數據參數被放入參數set之前的情況是這樣的:
1)請求是一個HTTP或一個HTTPS
2)HTTP方法是POST
3)內容的類型是application/x-www-form-urlencoded
4)初始化過的servlet從request對象中調用getParameter方法(或getParameterNames,
getParameterValues)。
Post form 中的數據符合條件的就放入參數set中,不符合的就放入request對象的輸入流中。
4.2 屬性
request的屬性是一個對象,引擎可以把API不能表達的信息放入屬性中,一個servlet也可以設
置一個屬性信息用于servlet之間的通信。request對象中的屬性方法有:
getAttribute
getAttributeNames
setAttribute
一個屬性名稱只能關聯一個value。屬性名以“java.”或“javax.”為前綴的是規范保留的,類似
的“sun.”“com.sun”是sun公司的保留字,這些保留的前綴是不能使用的。name建議使用統一的
包命名規范名稱。
4.3 頭
servlet通過HttpServletRequest接口的方法獲得HTTP的包頭信息,這些方法是:
getHeader
getHeaders
getHeaderNames
getHeader 方法返回頭的名稱。一個名稱可以關聯多個頭信息,如果在這種情況下,getHeader
方法返回第一個頭信息。
getHeaders返回與一個名稱關聯的所有頭信息存放在Enumeration對象中。HttpServletRequest
提供了一些提取頭信息的類型轉換方法,如:
getIntHeader 把頭信息中的數據轉換成int型,如果轉換失敗會報NumberFormatException錯
誤。
getDateHeader 把頭信息中日期的數據轉換成date型,如果轉換失敗會報
IllealArgumentException錯誤
4.4 請求路徑
context路徑:這路徑是和ServletContext對象關聯的,在web服務中默認的上下文路徑是空的字
符串,如果上下文路徑不是web服務的根目錄,則路徑以‘/’字符開始,但不能以‘/’結束。
Servlet 路徑:與該請求匹配的servlet的路徑。該路徑以‘/’字符開頭,或以‘/*’開頭但后面為空字
串。
路徑信息:是請求路徑的一部分,但不是context路徑的一部分,也不是Servlet路徑的一部分,
它既不為null也不是以‘/’開頭的字符串。
上一路徑在HttpServletRequest接口中對應的方法是:
getContextPath
getServletPath
getPathInfo
requestURI = contextPath + servletPath + pathInfo
上下文配置的例子:
Conteext Path /catalog
Servlet Mapping Pattern:/lawn/*
Servlet:LawnServlet
Servlet Mapping Pattern:/garden/*
Servlet:GardenServlet
Servlet Mapping Pattern:*.jsp
Servlet:JSPServlet
觀察下面的路徑
Request path path Elements
/catalog/lawn/index.htm ContextPath:/catalog
ServletPath:/lawn
PathInfo:/index.html
/catalog/garden/implements/
ContextPath:/catalog
ServletPath:/garden
PathInfo:/implements/
/catalog/help/feedback.jsp
ContextPath:/catalog
ServletPath:/help/feedback.jsp
PathInfo:null
4.5 路徑轉換
在API中有兩個簡單的方法允許開發者獲得文件系統的路徑:
ServletContext.getRealPath
HttpServletRequet.getPathTranslated
getRealPath(String aPath)方法返回本地文件系統的絕對路徑。getPathTranslated方法計算出請
求pathInfo中的絕對路徑。
以上的兩個方法,servlet引擎不能辨認文件的路徑是否有效,當web應用調用一個不確定遠程
文件系統,或數據庫路徑中的文件時,會返回null
4.6 Cookies
HttpServletRequest接口中提供了getCookies方法返回請求中的cookies數組,在每次客戶端請求
時cookies數據就從客戶端發送給服務。客戶端返還的部分cookie信息是cookie的name和cookie
的value。當cookie被送入瀏覽器時,cookie的其它信息就可以設置了。
4.7 SSL 屬性
如果一個請求被轉給一個安全的協議,如HTTPS,這些信息必須暴露給ServletRequest接口的
isSecure方法。web引擎必須把下面的信息暴露給servlet開發者:
Attribute Attribute Name javaType
Cipher suite javax.servlet.request.cipher_suite String
bit size of the algo-rithm javax.servlet.request.key_size Integer
如果一個SSL證書伴隨著一個請求,servlet引擎必須把它作為一個數組對象暴露給servlet開發
者,該數組中有
java.security.cert.X509Certificate對象和放在ServletRequest屬性中的javax.servlet.request.
X509Certificate對象。
數組排列的順序是升序,在鏈中的證書的順序就是客戶端設置的順序。
4.8 國際化
ServletRequest接口的方法中提供了的方法:
getLocale
getLocales
getLocale方法將返回客戶端將從中獲得內容的首選的locale。要想知道更多的關于Accept-
Language header 怎么解釋客戶端首選的語言的,請看14.4章
getLocales方法返回一個Locale objects的Enumeration,從首選的locale開始遞減。
如果客戶端沒有制定首選的locale,servlet引擎一定要提供一個默認的locale供getLocale方法返
回,getLocales方法必須包含一個默認的locale的locale element
4.9 Request 數據的編碼
有許多web瀏覽器不能發送一個編碼的頭內容,所以把編碼留給解讀HTTP請求的Read去做。對
于默認的請求編碼,引擎通常創建一個reader用“ISO-8859-1”去解析POST的數據,如果客戶端
沒有指明編碼,或者客戶端發送失敗,getCharacterEncoding方法就返回null。
如果客戶端沒有設置編碼,而請求需被另外一種編碼,可用ServletRequest接口中的
setCharacterEncoding(String enc) 方法。必須在解析post數據或讀取請求流之前調用這些方
法。
4.10 Request對象的生命周期
每個request對象僅在servlet的service方法或filter中的doFilter方法中有效,引擎重用request對
象是為了降低創建request對象的性能消耗。
開發者必須清楚request對象在給定的范圍外的一些不確定的行為。
第五章
response對象封裝著服務端送給客戶端的信息,從服務端傳回的信息可以包含在請求的頭和消息體重。
5.1 緩存
servlet引擎支持應答緩存,典型的servlet會默認的執行緩存,servlet可以指定緩存參數。
設置緩存信息的方法在ServletResponse接口中的方法有:
getBufferSize
setBufferSize
isCommitted
Reset
resetBuffer
flushBuffer
這些方法只有在servlet調用ServletOutputStream 或Writer之前有效。
getBufferSize返回緩存的大小,如果沒有緩存,該方法返回0。
setBufferSize可以設置緩存的大小,但不是必須的。servlet會根據請求放置適當的緩存大小。這方
法必須在servlet調用ServletOutputStream 或Writer方法之前被調用。如果在之后調用就會拋出
IllegalStateException錯誤。
isCommitted返回一個boolen值,標志是否有任何一個字節的數據被返回給客戶端了。flushBuffer
方法強制把緩存中的信息寫到客戶端。
當response沒有提交緩存內容時調用reset方法就會清除緩存中的信息,包括頭信息和狀態碼。
resetBuffer方法會清除緩存中的信息,但不會清除頭和狀態碼。在commit之后調用reset或
resetBuffer都會拋出IllegalStateException錯誤,緩存中的內容不受影響。
使用緩存時,當緩存滿時response就必須立刻刷新把緩存中的內容發送給客戶端;只要第一個字節
到了客戶端,commit的狀態就為true。
5.2 Headers
servlet能夠通過HttpServletResponse的一些方法設置HTTP響應的頭信息,這些方法有:
setHeader
addHeader
setHeader方法會把給定的一個name-values放到頭信息中,頭信息中只能有一個name-values,后面
setHeader會覆蓋前面setHeader方法中的內容,一個name可以有多個value。
addHeader方法可以增加一個value到已有的name上,如果name不同就會新建一個name-values
頭可以包含一些信息,如日期或數字對象。
以下的一些方法用適當的數據類型設置頭信息:
setIntHeader
setDateHeader
addIntHeader
addDateHeader
在響應被發送到客戶端之前,頭信息是必須被設置的,如果沒有設置頭信息,servlet引擎將不會發送該
請求到客戶端。HTTP1.1規范沒有規定必須設置響應的頭信息。當程序員沒有設置響應體的Content-
Type時,servlet引擎也不需要設置一個默認的類型。
5.3 其他一些方法
HttpServletResonse接口中還有其他的一些方法:
sendRedirect
sendError
sendRedirect方法將設置合適的頭和體信息,用于重定向客戶端到另一個URL。如果sendRedirect參數
是個相對路徑,則在底層servlet引擎中會把這相對路徑轉換成絕對路徑返回給客戶端的。
如果相對路徑不能被引擎轉換成絕對路徑就會拋出IllegalArgumentException錯誤。
sendError方法會把一條錯誤信息作為頭和體信息發送給客戶端。
如果在調用sendRedirect或sendError之前設置了頭和體信息,再調用sendRedirect或sendError時,之前
的頭和體中的數據信息都將沒用,不會被發送到客戶端。如果使用了緩存,在調用sendRedirect或
sendError時,之前的信息都將被清除。如果在commit之后調用sendRedirect或sendError就會拋出
IllegalStateException錯誤。
5.4 國際化
當客戶端用一特殊的語言(或客戶端設置了語言)發出請求時,servlet會設置相應的響應語言信息,
ServletResponse接口中設置響應語言的方法是setLocale。這個方法會設置一個合適的Content-
Language到頭信息中。最好是開發者在調用getWriter方法之前調用setLocale方法,確保返回的
PrintWriter已經被設置好了語言信息。如果在調用setLocale之后又調用了setContentType,setLocale中
的內容將被setContentType中的字符集覆蓋。
response默認的編碼方式是“ISO-8859-1”。
5.5 response對象的關閉
當response被關閉時,引擎必須刷新該response緩存中的所有內容到客戶端。關閉的順序是:
1)關閉servlet的service方法
2)response 中setContentLength方法設置的指定數量的信息被寫入response
3)調用sendError方法
4)調用sendRedirect方法
5.6 response對象的生命周期
每個response對象僅在servlet的serrvice方法或filter的doFilter的方法中有效。引擎重復使用reponse對
象,是為了降低創建response對象的開銷。開發者必須注意response對象在指定范圍外可能出現的一些
意外的行為。