基於Servlet的web應用交互過程
web應用通常是基於http的請求響應模式,一個使用servlet實現的web應用典型的交互過程以下:
1) 客戶端向web服務器發起一個HTTP請求;
2) HTTP請求被web服務器接受,並移交給servlet引擎;
3) servlet引擎根據配置決定調用那個servlet,並把request對象、response對象傳給它。
4) servlet經過request獲取用戶信息和請求的內容,servlet處理完請求後把要返回的信息放入response對象;
5)一旦servlet完成了請求的處理,servlet引擎就會刷新response,把控制權返回給web服務器;
6)web服務器將從servlet引擎獲取的內容返回給客戶端;
ServletRequest和ServletResponse
在Servlet規範中,ServletRequest表明客戶端對服務器的請求,ServletResponse表明服務器給給客戶端的響應;
其中,最重要的是HttpServletRequest 和 HttpServletResponse 這兩個子接口;
這兩個接口就是對http協議的請求和響應作面向對象的封裝。
HttpServletRequest
在基於servlet的web應用交互中,客戶端經過http協議發送請求至服務器,請求中會包含不少信息,如客戶端的瀏覽器信息以及請求內容等等;這些信息被包含在http頭和消息體中,而且以name-value的形式存在,一個name能夠對應多個value。
web服務器接到客戶端的http請求後會轉發給內部的servlet容器處理;
serlve容器拿到請求後,會解析http請求包含的信息,而後將這些信息封裝成HttpServletRequest對象,並傳給合適的servlet實例進行處理;
一、請求參數
經過HttpServletRequest的下列方法,能夠獲取這些參數信息:
- getParameter(String arg0)
- getParameterNames()
- getParameterValues(String arg0)
須要注意的是getParameterValues(String arg0)獲取的是與arg0對應的value數組,getParameter(String arg0)獲取的是value數組中的第一個值;
若是過URI中的參數爲a=1;POST中的參數爲a=2,a=3;請求中的參數a={1,2,3}。
若是
想獲取請求的路徑參數,則必須經過解析方法getRequestURI()或getPathInfo()返回的字符串。
二、屬性
request的屬性就是一些對象;
容器能夠將一些不能經過默認接口表達的信息經過屬性的方式設置到request中;
也能夠
設置一些屬性用來在servlet之間的通訊。
request對象中的關於屬性方法有:
- getAttribute(String arg0)
- getAttributeNames()
- setAttribute(String arg0,Object arg1)
與參數不一樣,這裏一個屬性名稱只能關聯一個value。
以「java.」或「javax.」爲前綴的屬性名是規範保留的,相似的「sun.」「com.sun」是sun公司的保留字,這些保留的前綴是不能使用的。
三、頭信息
經過HttpServletRequest的下列方法,servlet能夠獲取http請求的頭信息:
- getHeader
- getHeaders
- getHeaderNames
getHeader 方法返回頭的名稱。一個名稱能夠關聯多個頭信息,若是在這種狀況下,getHeader
方法返回第一個頭信息。
getHeaders返回與一個名稱關聯的全部頭信息存放在Enumeration對象中。
HttpServletRequest提供了一些提取頭信息的類型轉換方法,如:getIntHeader 把頭信息中的數據轉換成int型等。
四、請求路徑
一個請求映射到一個servlet上,其請求路徑包含了不少重要的部分,包括Context Path、Servlet Path、PathInfo。
其對應的方法有以下三個:
- getContextPath
- getServletPath
- getPathInfo
除了編碼方式不一樣外,下列等式是正確的:
requestURI = contextPath + servletPath + pathInfo
例如:
配置關係以下
Conteext Path: /catalog
Servlet:LawnServlet
Servlet Mapping Pattern:/lawn/*
Servlet:GardenServlet
Servlet Mapping Pattern:/garden/*
Servlet:JSPServlet
Servlet Mapping Pattern:*.jsp
注意下面的路徑的組成
/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
五、路徑轉換方法
在API中有兩個簡單的方法容許開發者得到文件系統的路徑:
- ServletContext.getRealPath
- HttpServletRequet.getPathTranslated
getRealPath(String aPath)方法返回本地文件系統的絕對路徑。
getPathTranslated方法計算出請求pathInfo中的絕對路徑。
以上的兩個方法,servlet引擎不能辨認文件的路徑是否有效,當web應用調用一個不肯定遠程文件系統,或數據庫路徑中的文件時,會返回null。
六、cookie
HttpServletRequest接口中提供了getCookies方法來返回請求中的cookies數組;
在每次客戶端請求時cookies數據就從客戶端發送給服務器。
客戶端返回的cookie信息是cookie的name和cookie的value。
當cookie被髮送至瀏覽器時,cookie的信息就會被設置。
七、SSL屬性
若是一個請求是經過一個安全協議進行傳輸的,例如HTTPS,那麼這個信息必須經過ServletRequest的isSecure方法進行暴露。並且web容器必須將下列屬性暴露給開發人員:
Attribute |
Atrribute Name |
Java type |
Cipher suite |
javax.servlet.request.cipher_suite |
String |
bit size of the algo-rithm |
javax.servlet.request.key_size |
Integer |
若是過一個請求中包含一個SSL證書信息,servlet引擎必須把它做爲一個數組對象暴露給servlet開發者,能夠經過ServletRequest屬性中的javax.servlet.request.X509Certificate屬性得到,該數組的類型爲java.security.cert.X509Certificate。
數組排列的順序是按照信任程度的升序,第一個證書是客戶端設置的,第二個用來驗證第一個,以此類推。
八、國際化
客戶端能夠經過http頭信息的
Accept-Language來告訴web服務器客戶端想要哪種語言的響應;
ServletRequest中提供的相關方法以下:
getLocale方法將返回客戶端首選的Locale。
getLocales方法返回一個Enumeration,從首選的locale開始遞減。
若是客戶端沒有制定首選的locale,
servlet引擎必定要提供一個默認的locale供getLocale方法返回,getLocales方法必須包含一個默認的locale的locale element
九、請求數據的編碼
有許多web瀏覽器不發送帶有「content-type」頭信息的字符編碼限定符,
而由讀取http請求的代碼來決定字符的編碼方式。
默認狀況下,
若是客戶端請求未定義編碼限定符,容器(如tomcat)會用「ISO-8859-1」去建立request reader和解析POST的數據;
爲了向開發者指明客戶端沒有發送字符編碼信息的狀況,容器對getCharacterEncoding方法返回null。
若是客戶端不設置字符編碼方式,而且request不是按照以上缺省編碼方式(ISO-8859-1)來編碼,則會發生問題。
爲了解決這個問題,在接口ServletRequest中加入了一個新的方法setcharacterencoding(string encoding)。開發者能夠調用這個方法來替換包容器提供的缺省字符編碼方式。
可是,必須在從request中分析任何post數據或者讀取任何輸入以前調用這個方法。
一旦數據已被讀取,則調用這個方法將不會影響編碼方式。
注意:
自從Tomcat5.x開始,GET和POST方法提交的信息,tomcat採用了不一樣的方式來處理編碼,對於POST請求,Tomcat會仍然使用request.setCharacterEncoding方法所設置的編碼來處理,若是未設置,則使用默認的iso-8859-1編碼。而GET請求則不一樣,Tomcat對於GET請求並不會考慮使用request.setCharacterEncoding方法設置的編碼,而會永遠使用iso-8859-1編碼
十、request對象的生命週期
request對象只有在servlet的service()方法或者filter的doFilter()方法中才有效;
爲了不建立request對象的性能消耗,
容器會重用request對象;
因此不能在上述範圍之外持有對request的引用,不然會出現難以預料的錯誤。
HttpServletResponse
請求被servlet處理後,通常都會返回處理的結果信息,這些信息被封裝到HttpServletResponse對象中並返回給servlet容器;
servlet容器將HttpServletResponse對象轉化成http響應交給web服務器,web服務器獲得響應後將其轉發給客戶端;
一、緩存
爲了提升效率,servlet容器容許將發送給客戶端的內容進行緩存;典型的服務器都會使用緩存,而且容許servlet指定緩存參數。
ServletRequest接口中關於緩存的方法以下:
- getBufferSize
- setBufferSize
- isCommitted
- Reset
- resetBuffer
- flushBuffer
這些方法只在servlet調用ServletOutputStream或者Writer以前有效。
當使用的緩存已滿時,容器必須馬上刷新把緩存的內容發送到客戶端,若是這是第一個被髮送到客戶端的數據,那麼response也會被認爲是已提交。
二、頭信息
servlet能夠經過ServletResponse接口設置響應的頭信息,以下方法:
- setHeader
- addHeader
- setIntHeader
- setDateHeader
- addIntHeader
- addDateHeader
在response被提交前頭信息必須被設置,不然無效。
開發人員有責任設置Content-Type頭信息,用來表示servlet生成的內容類型。
HTTP1.1規範沒有要求設置這個頭信息,因此當開發人員沒有設置這個類型時容器不必設置一個默認值。
三、簡單的方法
在HttpServletResponse接口中有下列簡單的方法:
sendRedirect方法會設置合適的頭信息和消息體,使客戶端重定向到兩一個url;
若是參數是一個相對路徑,底層容器會將其轉換成絕對路徑發送給客戶端;若是轉換失敗則拋出IllegalArgumentException;
sendError方法同上。
四、國際化
servlet應該設置一個response的local和字符編碼。
local使用ServletRespnse的setLocal方法,若是response被提交前沒有設置local,容器的默認local會被使用。
setCharacterEncoding用來設置字符編碼,response默認的編碼方式是「ISO-8859-1」。
五、response對象的關閉
當一個response對象被關閉,容器必須當即將緩存中的內容發送給客戶端。下列條件表示servlet已經知足請求的內容並關閉response對象:
- servlet方法service結束;
- response中經過setContentLength設置的指定數量的信息被寫入到response;
- 調用sendError方法;
- 調用sendRedirect方法。
六、response對象的生命週期
同request對象的生命週期。
問題:
一、HttpServletRequest對象是怎麼被容器重用的?
能夠參考http://bbs.csdn.net/topics/300088535