| Servlet2.3規(guī)范 第一章: servlet2.3規(guī)范用到了一下的一些規(guī)范:J2EE、JSP1.1、JNDI 在14章中講述了規(guī)范中的所有的classes類或接口(改文中不講述)。對開發(fā)者而言以下的有些相關(guān)的協(xié)議:URI、URL、HTTP/1.0、MIME、HTCPCP/1.0、XML 1.1 什么是servlet? servlet是一個基于java技術(shù)的web組件,該組件被容器管理,能被編譯成字節(jié)碼被web服務(wù)調(diào)用;容器也被稱之為引擎,是支持servlet功能的web服務(wù)的擴展。servlet之間的通信是通過客戶端請求被引擎執(zhí)行成request/response對象進行的。 1.2 什么是servlet引擎? servlet引擎是web服務(wù)器或應(yīng)用服務(wù)器的一部分,服務(wù)器能夠支持網(wǎng)絡(luò)的請求/響應(yīng),基于請求解析MIME,基于響應(yīng)格式化MIME。servlet引擎是一個servlet容器,也掌管著servlet的生命周期。 所有的servlet引擎都必須支持HTTP的請求/響應(yīng)模式,但HTTPS的請求/響應(yīng)模式也是被支持的。HTTP的版本最小要HTTP/1.0,最好是HTTP/1.1。servlet引擎也具有安全和權(quán)限的一些特性,這些特性其服務(wù)器應(yīng)提供。 1.3 例子 一個典型的事件執(zhí)行的順序是: 1)       客戶端向web服務(wù)器發(fā)起一個HTTP請求 2)       HTTP請求被web服務(wù)器接受,并移交給servlet引擎,servlet引擎可以在主機的同一個進程、不同的進程或其他的web服務(wù)主機的進程中啟動。 3)       servlet引擎根據(jù)servlet的配置檔確定調(diào)用的servlet,并把request對象、response對象傳給它。 4)       4.servlet通過request對象知道客戶端的使用者是誰,客戶的請求信息是什么和其他的一些信息。servlet處理完請求后把要返回的信息放入response對象返回到客戶端 5) 一旦servlet完成了請求的處理,servlet引擎就會刷新response,把控制權(quán)返回給web服務(wù)器 1.4與其它技術(shù)的比較 與其它服務(wù)相比servlet有以下的一些優(yōu)點 1)       運行速度上比CGI快,因為使用了多線程 2)       servlet使用了標準的api,可被許多web服務(wù)支持 3)       與系統(tǒng)無關(guān)性,一次編譯多次使用 第二章 servlet接口是servlet api核心部分,所有的servlet都是直接或間接的實現(xiàn)了這些接口。兩個最重要的servlet api 接口是GenericServlete 和 HttpServlet,更多的開發(fā)者都繼承HttpServlet去實現(xiàn)他們的servlet 2.1 Request 包含的方法 一個基本的servlet接口應(yīng)該定義一個方法包含客戶端的信息,每次servlet引擎把一個request發(fā)送到一個servlet事例,這個方法都要被調(diào)用。 對于并發(fā)的請求,web應(yīng)用需要設(shè)計者設(shè)計的servlet引擎能分配多個線程執(zhí)行這個方法。 2.1.1 HTTP 請求處理的方法 HttpServlet是實現(xiàn)了Servlet接口的抽象類,增加了一些新的方法,這些方法在處理HTTP請求時會被service方法自動調(diào)用,這些方法是: doGet 接受 HTTP 的GET請求 doPost 接受 HTTP 的POST請求 doPut 接受 HTTP的PUT請求 doDelete 接受 HTTP的DELETE請求 doHead 接受 接受 HTTP的HEAD請求 doOptions 接受 HTTP的OPTIONS請求 doTrace 接受 HTTP的TRACE請求 一個開發(fā)者只會涉及到doGet和doPost方法,其它的方法是為非常熟悉HTTP的設(shè)計師準備的 2.1.2 HTTP/1.0只定義了doGet,doHead,doPost方法,沒有定義PUT,DELETE,OPTIOONS和TRACE方法 2.1.3  HttpServlet接口定義了getLastModified方法 2.2 實例數(shù) 2.2.1 在分布式環(huán)境中servlet引擎為每個servlet只能聲明一個實例,當一個servlet實現(xiàn)了SingleThreadModel接口時,servlet引擎可以聲明多個實例去處理請求,servlet在應(yīng)用服務(wù)的部署描述中定義發(fā)布. 2.2.2單線程servlet SingleThreadModel接口保證了在同一時刻一個servlet實例的service方法只會被一個線程執(zhí)行。這對于每個請求發(fā)送給每個實例是很重要的。引擎可以從對象池中選擇,對象池可以在同一時刻保持多個實例,如HttpSession可以被多個servlet在任何時候調(diào)用包括實現(xiàn)了SingleThreadModel接口的servlet 2.3 servlet的生命周期      一個好的生命周期的定義應(yīng)該是servlet怎么被引入了,怎么實例化的,怎么初始化的?當請求從客戶端來的時候,是怎么從服務(wù)器中取出來的,這些在javax.servlet.Servlet的接口的init,service,destroy方法中都有明確的定義。 所有的servlet都必須實現(xiàn)GenericServlet或HttpServlet抽象類 2.3.1 servlet的引入和實例化 servlet引擎會可靠的引入和實例化servlet,當servlet引擎被啟動時servlet就被引入和實例化了,或者當一個servlet被請求時被引擎引入和實例化。 servlet引擎啟動時,需要裝載的類通過java的裝載類進行裝載,被裝載的類可以在本地文件系統(tǒng)、遠程文件系統(tǒng)或網(wǎng)絡(luò)服務(wù)中。在裝載完后,引擎就實例化它們。 2.3.2 初始化 在servlet對象實例化后,引擎必須在這個servlet接受客戶段請求之前初始化,在初始化中servlet可以讀取固定的配置信息,一些昂貴的資源如數(shù)據(jù)庫連接和一次性激活的資源,引擎通過調(diào)用servlet接口的init方法初始化。每個serlet對象都實現(xiàn)了Servlet接口和ServletConfig接口,ServletConfig接口允許servlet接受web應(yīng)用配置檔中配置的參數(shù),還向servlet中傳入了一個描述servlelt運行環(huán)境的類(ServletContext) 2.3.2.1 在初始化時發(fā)生錯誤 在初始化過程中,servlet實例能拋出UnavailableException 或ServletException異常。在這樣的情況下servlet不能被放入服務(wù)中,必須被引擎釋放,destroy方法沒有被調(diào)用。在初始化失敗后引擎可以在UnavailableException異常規(guī)定的最短無效時間后實例化新的一個實例,再初始化。 2.3.3 request 當servlet初始化完成后,引擎可以使用它去處理客戶端的請求了。請求被封裝在Servletrequest類型的對象中,響應(yīng)信息被封裝在ServletResponse類型的對象中,這兩個對象以參數(shù)的形式傳給Servlet接口中的service方法。 2.3.3.1 多線程問題 servlet引擎可以發(fā)送并發(fā)的請求給servlet的service方法,servlet開發(fā)者必須提供足夠的線程來運行service方法。 對開發(fā)者來說一個可以選擇的方法是實現(xiàn)SingleThreadModel接口,以確保在同一時刻只有一個請求在service方法中。一個引擎要確保請求能夠在servlet中持續(xù)化,或維持在一個servlet實例池中,如果servlet是web應(yīng)用服務(wù)的一部分,引擎可以在一個虛擬機中擁有一個servlet實例化的池。 對于沒有實現(xiàn)SingleThreadModel接口的servlet,如果service方法(或 doGet,doPost)被聲明為synchronized,引擎將不能用實例池的途徑,而必須持續(xù)化請求,強力建議開發(fā)者不能聲明synchronize service方法,這樣會嚴重影響系統(tǒng)的性能。 2.3.3.2 request中的異常 在處理請求時servlet可以拋出ServletException或UnavailableException異常,一個ServletException異常會在處理一個請求出現(xiàn)錯誤時拋出,引擎將清除這個異常。當servlet一時或永久地不能獲得一個請求時就會拋出UnavailableException異常,如果是一個永久性異常時引擎將調(diào)用它的destroy方法從服務(wù)器中消除servlet實例,如果是暫時性異常時引擎在異常期間不發(fā)送請求給servlet。如果返回SERVICE_UNAVAILABLE(503)響應(yīng),在這期間引擎將不接受任何請求,直到header中出現(xiàn)Retry-After。引擎可以不區(qū)分永久性還是暫時性的異常把所有的UnavailableException作為永久性處理。 2.3.3.3 線程安全 執(zhí)行request和response對象不能保證是線程安全的,意思是說他們只能在請求的線程中使用,不能被其它線程中的對象使用。 2.3.4 結(jié)尾 servlet實例可能被引擎保存幾毫秒或和引擎一樣的生命時間或在這兩者之間。當引擎決定結(jié)束一個servlet時,調(diào)用它的destroy方法,在destroy中釋放任何長久固定的資源。 在引擎調(diào)用desroy方法之前,必須保證運行在service方法中的線程都完成處理,或者超過了服務(wù)定義的執(zhí)行時間。 一旦servlet實例的destroy方法被調(diào)用,引擎不在發(fā)送任何請求給這個實例。如果引擎再次使用這個servlet就必須再建一個這個servlet的實例。 在destroy方法執(zhí)行完成后,引擎將釋放這個servlet實例,于是就符合垃圾回收機制的條件了。 3.1 介紹ServletContext接口 ServletContext接口定義了servlet運行環(huán)境的信息。引擎提供商有義務(wù)在servlet引擎中提供一個實現(xiàn)了ServletContext接口的對象。通過這個對象servlet能夠獲得log事件,資源的URL,設(shè)置或存儲servlet之間通信的變量。ServletContext在web服務(wù)中確定了一個所有請求開始的路徑,是ServletContext的上下文路徑。 3.2 ServletContext 接口的作用范圍 每個web應(yīng)用配置到容器中都會產(chǎn)生一個實現(xiàn)了ServvletContext接口的實例。如果是分布式的,將會在每個java虛擬機上產(chǎn)生一個ServletContext實例。容器中默認固有的web應(yīng)用(不是發(fā)布上來的web應(yīng)用)有一個默認的ServletContext,在分布式中這個默認的ServletContext只存在于一個虛擬機中,是不可分配的。 3.3 初始化參數(shù) ServletContext接口的getInitParameter,getInitParameterNames方法接受部署描述文件中的初始化參數(shù),這些參數(shù)可以是的安裝信息,或網(wǎng)站管理員的mail或名字或?qū)ο到y(tǒng)的評論。 3.4 上下文屬性 servlet可以通過一個名稱把對象邦定到servletContext中,幫定到ServletContext中的對象都能被同一個web服務(wù)中的其它對象引用。ServletContext中的屬性方法有: setAttribute getAttribute getAttributeNames removeAttribute 3.4.1 在分布式系統(tǒng)中 上下文的屬性 上下文屬性是在本地的虛擬機中保存的,這防止了ServletContext屬性存在于分布式的內(nèi)存中。當信息需要在一個分布式環(huán)境中共享的時候,信息應(yīng)該被放在session中,或存在數(shù)據(jù)庫中,或存在一個實體bean中。 3.5 資源 ServletContext接口提供了獲取web服務(wù)中的靜態(tài)資源的方法: getResource getResourceAsStream 這些方法以一個“/”作為上下文的根目錄,后跟著資源路徑的路徑為參數(shù)。這些資源可以在本地服務(wù)系統(tǒng)中也可以在另個web應(yīng)用中,或在一個遠程的文件系統(tǒng)中。 這些方法不能用于去獲得一個動態(tài)的資源,如要調(diào)用一個jsp頁面,getResource("/index.jsp")將返回index.jsp的原代碼,不能web顯示index.jsp。 要獲得資源列表可以用getResourcePaths(String path)方法 3.6 多主機 和 Servlet 上下文 web服務(wù)中可能在一個IP上有多個邏輯主機的情況。在這種情況下每個邏輯主機必須有自己單獨的servlet上下文,或者設(shè)置多個servlet 上下文,但在邏輯主機中不能共享這些servlet 上下文,一個主機只能單獨使用一個。 3.7  引擎提供類重新裝載機制是必須的,必須確認應(yīng)用中所有的類和接口都可以在單類裝載器中裝載;在session綁定監(jiān)聽事件中引擎會終止正在裝在的類。以前版本的裝載器,引擎創(chuàng)建一個新的裝載器裝載一個servlet或class和類裝載器裝載其他的servlet或類截然不同;這可能裝載一個未知的類或?qū)ο?,產(chǎn)生不可預(yù)知的行為。這是新的類裝載器中是應(yīng)該注意預(yù)防的問題。 3.7.1 臨時工作目錄 Servlet 上下文需要一個臨時存儲的目錄。servlet引擎必須為每個servlet 上下文提供一個私有臨時目錄,通過javax.servlet.context.tempdir的context屬性使目錄有效。與該屬性關(guān)聯(lián)的對象必須是java.io.File類型。  在許多servlet引擎實現(xiàn)中提供請求可以識別的通用的機制。 當servlet引擎重起始不必維護臨時目錄中的內(nèi)容,但要確保臨時目錄中的該上下文內(nèi)容對于運行在該servlet引擎中的其它web應(yīng)用中的servlet 上下文是不可見的。 4 requeset request對象包含了客戶端的所有請求信息。在HTTP協(xié)議中,客戶端發(fā)送到服務(wù)端的信息都包含在請求的HTTP 頭和消息體中 4.1 HTTP 協(xié)議的參數(shù) 客戶端發(fā)送給servlet引擎的參數(shù)是包含在請求中的,引擎從客戶端請求的URI字符串中或POST數(shù)據(jù)中解析出請求的參數(shù)。參數(shù)以name-value的形式存儲的。任何一個name可以對應(yīng)多個value。在ServletRequest接口的方法中: getParameter getParameterNames getParameterValues getParameterValues方法返回關(guān)聯(lián)到一個name上的一個String對象的數(shù)組。getParameter返回name對應(yīng)的values數(shù)組中的第一個value。URI和POST體中的參數(shù)都會放入請求參數(shù)的set對象中。URI中的參數(shù)會在POST體之前被引入,如URI中的參數(shù)“a=hello”post體中的參數(shù)是a=goodbye&a=world,則參數(shù)set中的內(nèi)容是a=(hello,goodbye,world).以HTTP GET請求的參數(shù)是不隱蔽的,參數(shù)必須通過getRequestURI或getPathInfo方法獲得參數(shù)字串。 4.1.1 參數(shù)什么時候有效 在post form中的數(shù)據(jù)參數(shù)被放入?yún)?shù)set之前的情況是這樣的: 1)請求是一個HTTP或一個HTTPS 2)HTTP方法是POST 3)內(nèi)容的類型是application/x-www-form-urlencoded 4)初始化過的servlet從request對象中調(diào)用getParameter方法(或getParameterNames,getParameterValues)。 Post form 中的數(shù)據(jù)符合條件的就放入?yún)?shù)set中,不符合的就放入request對象的輸入流中。 4.2 屬性 request的屬性是一個對象,引擎可以把API不能表達的信息放入屬性中,一個servlet也可以設(shè)置一個屬性信息用于servlet之間的通信。request對象中的屬性方法有: getAttribute getAttributeNames setAttribute 一個屬性名稱只能關(guān)聯(lián)一個value。屬性名以“java.”或“javax.”為前綴的是規(guī)范保留的,類似的“sun.”“com.sun”是sun公司的保留字,這些保留的前綴是不能使用的。name建議使用統(tǒng)一的包命名規(guī)范名稱。 4.3 頭 servlet通過HttpServletRequest接口的方法獲得HTTP的包頭信息,這些方法是: getHeader getHeaders getHeaderNames getHeader 方法返回頭的名稱。一個名稱可以關(guān)聯(lián)多個頭信息,如果在這種情況下,getHeader方法返回第一個頭信息。 getHeaders返回與一個名稱關(guān)聯(lián)的所有頭信息存放在Enumeration對象中。HttpServletRequest提供了一些提取頭信息的類型轉(zhuǎn)換方法,如: getIntHeader 把頭信息中的數(shù)據(jù)轉(zhuǎn)換成int型,如果轉(zhuǎn)換失敗會報NumberFormatException錯誤。 getDateHeader 把頭信息中日期的數(shù)據(jù)轉(zhuǎn)換成date型,如果轉(zhuǎn)換失敗會報IllealArgumentException錯誤 4.4 請求路徑 context路徑:這路徑是和ServletContext對象關(guān)聯(lián)的,在web服務(wù)中默認的上下文路徑是空的字符串,如果上下文路徑不是web服務(wù)的根目錄,則路徑以‘/’字符開始,但不能以‘/’結(jié)束。 Servlet 路徑:與該請求匹配的servlet的路徑。該路徑以‘/’字符開頭,或以‘/*’開頭但后面為空字串。 路徑信息:是請求路徑的一部分,但不是context路徑的一部分,也不是Servlet路徑的一部分,它既不為null也不是以‘/’開頭的字符串。 上一路徑在HttpServletRequest接口中對應(yīng)的方法是: 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 路徑轉(zhuǎn)換 在API中有兩個簡單的方法允許開發(fā)者獲得文件系統(tǒng)的路徑: ServletContext.getRealPath HttpServletRequet.getPathTranslated getRealPath(String aPath)方法返回本地文件系統(tǒng)的絕對路徑。getPathTranslated方法計算出請求pathInfo中的絕對路徑。 以上的兩個方法,servlet引擎不能辨認文件的路徑是否有效,當web應(yīng)用調(diào)用一個不確定遠程文件系統(tǒng),或數(shù)據(jù)庫路徑中的文件時,會返回null 4.6 Cookies HttpServletRequest接口中提供了getCookies方法返回請求中的cookies數(shù)組,在每次客戶端請求時cookies數(shù)據(jù)就從客戶端發(fā)送給服務(wù)??蛻舳朔颠€的部分cookie信息是cookie的name和cookie的value。當cookie被送入瀏覽器時,cookie的其它信息就可以設(shè)置了。 4.7 SSL 屬性 如果一個請求被轉(zhuǎn)給一個安全的協(xié)議,如HTTPS,這些信息必須暴露給ServletRequest接口的isSecure方法。web引擎必須把下面的信息暴露給servlet開發(fā)者: 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引擎必須把它作為一個數(shù)組對象暴露給servlet開發(fā)者,該數(shù)組中有 java.security.cert.X509Certificate對象和放在ServletRequest屬性中的javax.servlet.request.X509Certificate對象。 數(shù)組排列的順序是升序,在鏈中的證書的順序就是客戶端設(shè)置的順序。 4.8 國際化 ServletRequest接口的方法中提供了的方法: getLocale getLocales getLocale方法將返回客戶端將從中獲得內(nèi)容的首選的locale。要想知道更多的關(guān)于Accept-Language header 怎么解釋客戶端首選的語言的,請看14.4章 getLocales方法返回一個Locale objects的Enumeration,從首選的locale開始遞減。 如果客戶端沒有制定首選的locale,servlet引擎一定要提供一個默認的locale供getLocale方法返回,getLocales方法必須包含一個默認的locale的locale element 4.9 Request 數(shù)據(jù)的編碼 有許多web瀏覽器不能發(fā)送一個編碼的頭內(nèi)容,所以把編碼留給解讀HTTP請求的Read去做。對于默認的請求編碼,引擎通常創(chuàng)建一個reader用“ISO-8859-1”去解析POST的數(shù)據(jù),如果客戶端沒有指明編碼,或者客戶端發(fā)送失敗,getCharacterEncoding方法就返回null。 如果客戶端沒有設(shè)置編碼,而請求需被另外一種編碼,可用ServletRequest接口中的setCharacterEncoding(String enc) 方法。必須在解析post數(shù)據(jù)或讀取請求流之前調(diào)用這些方法。 4.10 Request對象的生命周期 每個request對象僅在servlet的service方法或filter中的doFilter方法中有效,引擎重用request對象是為了降低創(chuàng)建request對象的性能消耗。 開發(fā)者必須清楚request對象在給定的范圍外的一些不確定的行為。 第五章 response對象封裝著服務(wù)端送給客戶端的信息,從服務(wù)端傳回的信息可以包含在請求的頭和消息體重。 5.1 緩存     servlet引擎支持應(yīng)答緩存,典型的servlet會默認的執(zhí)行緩存,servlet可以指定緩存參數(shù)。     設(shè)置緩存信息的方法在ServletResponse接口中的方法有: getBufferSize setBufferSize isCommitted Reset resetBuffer flushBuffer 這些方法只有在servlet調(diào)用ServletOutputStream 或Writer之前有效。 getBufferSize返回緩存的大小,如果沒有緩存,該方法返回0。 setBufferSize可以設(shè)置緩存的大小,但不是必須的。servlet會根據(jù)請求放置適當?shù)木彺娲笮?。這方法必須在servlet調(diào)用ServletOutputStream 或Writer方法之前被調(diào)用。如果在之后調(diào)用就會拋出IllegalStateException錯誤。 isCommitted返回一個boolen值,標志是否有任何一個字節(jié)的數(shù)據(jù)被返回給客戶端了。flushBuffer方法強制把緩存中的信息寫到客戶端。 當response沒有提交緩存內(nèi)容時調(diào)用reset方法就會清除緩存中的信息,包括頭信息和狀態(tài)碼。resetBuffer方法會清除緩存中的信息,但不會清除頭和狀態(tài)碼。在commit之后調(diào)用reset或resetBuffer都會拋出IllegalStateException錯誤,緩存中的內(nèi)容不受影響。 使用緩存時,當緩存滿時response就必須立刻刷新把緩存中的內(nèi)容發(fā)送給客戶端;只要第一個字節(jié)到了客戶端,commit的狀態(tài)就為true。 5.2 Headers servlet能夠通過HttpServletResponse的一些方法設(shè)置HTTP響應(yīng)的頭信息,這些方法有: setHeader addHeader setHeader方法會把給定的一個name-values放到頭信息中,頭信息中只能有一個name-values,后面setHeader會覆蓋前面setHeader方法中的內(nèi)容,一個name可以有多個value。 addHeader方法可以增加一個value到已有的name上,如果name不同就會新建一個name-values 頭可以包含一些信息,如日期或數(shù)字對象。 以下的一些方法用適當?shù)臄?shù)據(jù)類型設(shè)置頭信息: setIntHeader setDateHeader addIntHeader addDateHeader 在響應(yīng)被發(fā)送到客戶端之前,頭信息是必須被設(shè)置的,如果沒有設(shè)置頭信息,servlet引擎將不會發(fā)送該請求到客戶端。HTTP1.1規(guī)范沒有規(guī)定必須設(shè)置響應(yīng)的頭信息。當程序員沒有設(shè)置響應(yīng)體的Content-Type時,servlet引擎也不需要設(shè)置一個默認的類型。 5.3 其他一些方法 HttpServletResonse接口中還有其他的一些方法: sendRedirect sendError sendRedirect方法將設(shè)置合適的頭和體信息,用于重定向客戶端到另一個URL。如果sendRedirect參數(shù)是個相對路徑,則在底層servlet引擎中會把這相對路徑轉(zhuǎn)換成絕對路徑返回給客戶端的。 如果相對路徑不能被引擎轉(zhuǎn)換成絕對路徑就會拋出IllegalArgumentException錯誤。 sendError方法會把一條錯誤信息作為頭和體信息發(fā)送給客戶端。 如果在調(diào)用sendRedirect或sendError之前設(shè)置了頭和體信息,再調(diào)用sendRedirect或sendError時,之前的頭和體中的數(shù)據(jù)信息都將沒用,不會被發(fā)送到客戶端。如果使用了緩存,在調(diào)用sendRedirect或sendError時,之前的信息都將被清除。如果在commit之后調(diào)用sendRedirect或sendError就會拋出IllegalStateException錯誤。 5.4 國際化 當客戶端用一特殊的語言(或客戶端設(shè)置了語言)發(fā)出請求時,servlet會設(shè)置相應(yīng)的響應(yīng)語言信息,ServletResponse接口中設(shè)置響應(yīng)語言的方法是setLocale。這個方法會設(shè)置一個合適的Content-Language到頭信息中。最好是開發(fā)者在調(diào)用getWriter方法之前調(diào)用setLocale方法,確保返回的PrintWriter已經(jīng)被設(shè)置好了語言信息。如果在調(diào)用setLocale之后又調(diào)用了setContentType,setLocale中的內(nèi)容將被setContentType中的字符集覆蓋。 response默認的編碼方式是“ISO-8859-1”。 5.5 response對象的關(guān)閉 當response被關(guān)閉時,引擎必須刷新該response緩存中的所有內(nèi)容到客戶端。關(guān)閉的順序是:  1)關(guān)閉servlet的service方法  2)response 中setContentLength方法設(shè)置的指定數(shù)量的信息被寫入response  3)調(diào)用sendError方法  4)調(diào)用sendRedirect方法 5.6 response對象的生命周期 每個response對象僅在servlet的serrvice方法或filter的doFilter的方法中有效。引擎重復(fù)使用reponse對象,是為了降低創(chuàng)建response對象的開銷。開發(fā)者必須注意response對象在指定范圍外可能出現(xiàn)的一些意外的行為。 6 Filtering Fileter是servlet2.3新增的部分。這一章介紹Filter類和方法,以及在web工程中的配置。 6.1什么是Fileter Filter是重復(fù)使用的,用于變換HTTP請求和響應(yīng)以及頭信息中的內(nèi)容。Filter不能像servlet那樣創(chuàng)建response響應(yīng),但可以修改請求和響應(yīng)的內(nèi)容。 6.1.1例舉一些Filter 驗證Filter 登陸,審核Filter 圖像處理Filter 數(shù)據(jù)壓縮Filter 加密Filter XSL/T Filter MIME Filter 6.2 主要觀念 開發(fā)者通過創(chuàng)建實現(xiàn)javax.servlet.Filter接口的類,并提供一個沒有參數(shù)的構(gòu)造函數(shù)來創(chuàng)建一個Filter。 在描述文件中Fileter用filter表示,調(diào)用方法用filter-mapping進行配置。 6.3 Filter生命周期 在web工程發(fā)布后,在請求使引擎訪問一個web資源之前,引擎必須定位Filter列表;引擎必須確保為列表中的每一個Filter建立了一個實例,并調(diào)用了他們的init(FilterConfig config)方法。在這過程中可以拋出異常。 部署描述文件中定義的所有filter,僅會在引擎中產(chǎn)生一個實例。 引擎為filter提供了一個FilterConfig類,該類附有ServletContext和一個帶有初始化參數(shù)的set。 當引擎接受一個請求時,引擎就會調(diào)用filter列表中第一個filter的doFilter方法,把ServletRequest,ServletResponse和FilterChain作為參數(shù)傳給它。 filter中doFilter方法典型的處理步驟是: 1)檢查請求頭信息 2)開發(fā)者創(chuàng)建一個實現(xiàn)了ServletRequest或HttpServletRequest的類,去包裝request對象,以便修改請求的頭信息或體數(shù)據(jù)。 3)開發(fā)者創(chuàng)建一個實現(xiàn)了ServletReqponse或HttpServletResponse的類,去包裝response對象,以便修改請求的頭信息或體數(shù)據(jù)。 4)filter可以調(diào)用鏈中的下一個實體,下一個實體是另一個filter,如果該filter是列表中最后的一個,則它的下一個實體就是一個目標web資源。如果要調(diào)用下一個filter的doFilter方法,把request,和response對象傳給FilterChain對象的doFilter方法中就可以了。 Filter chain 的doFilter方法是由引擎提供的,引擎在該方法中會定位filter列表中的下一個filter,調(diào)用它的doFilter方法,把傳來的request和response對象傳給它。 5)在調(diào)用chain.doFilter之后,filter可以檢測響應(yīng)的頭信息 6)在這些過程中,filter可以拋出異常。當在調(diào)用doFilter過程中拋出UnavailableException異常時,引擎重復(fù)嘗試處理下面的filter chain的方法,如過時后還沒請求到filter chain 就會關(guān)閉對filter chain的請求。 當filter是列表中最后一個filter時,它的下一個實體是描述配置文件中filter后面的servlet或其它資源。 在引擎刪除一個Filter之前,引擎必須調(diào)用Filter的destroy方法,來釋放資源。 6.3.1 包裝Requests 和Responsees 過濾的中心觀念是對request或response的包裝,在這種模式下,開發(fā)者不僅可以改寫存在的方法,還可以創(chuàng)建自己的新方法,用于特殊的過濾任務(wù),例如:開發(fā)者希望擴展response對象,希望有個更高層次的輸出流對象(writer)。 為了支持包裝模式,引擎不許保證在整個過濾鏈中,傳遞的request和response對象都是同一個對象。 6.3.2 Filter的環(huán)境 Filter的初始參數(shù)可以在描述配置文件中用init-params元素來配置,在運行時中,用FilterConfig的getInitParameter和getInitParamesterNames方法得到配置參數(shù)。 6.3.3 Filter在web工程中的配置 在部署描述文件中: filter-name:filter名稱 filter-class:filter類路徑 init-params:用于初始化參數(shù) 如果開發(fā)者在部署描述中為一個filter類描述了兩個定義,則引擎會創(chuàng)建這個filter類的兩個實例。 下面是個配置的例子: <filter> <filter-name>Image Filter</filter-name> <filter-class>com.acme.ImageServlet</fiflter-class> </filter> 一旦filter在部署描述中定義,filter-mapping就可以被定義了,filter-mapping在web應(yīng)用中是定義關(guān)聯(lián)filter的servlet和靜態(tài)資源的。 如: <filter-mapping> <filter-name>Image Filter</filter-name> <servlet-name>ImageServlet</servlet-name> </filter-mapping> Image Filter 的 Filter就和ImageServlet 的Servlet建立了關(guān)聯(lián)。 Filter 可以和一群servlet和靜態(tài)資源關(guān)聯(lián),用url-pattern。如: <filter-mapping> <filter-name>Loging Filter</filter-name> <url-pattern>/*</url-pattern> <filter-mapping> 引擎建立特殊請求URI的Filter鏈的順序是: 1)url-pattern映射fiter-mapping的順序和描述文件中定義的順序是一樣的。 2)servlet-name映射filter-mapping的順序和描述文件中定義的順序是一樣的。 這種需求要求引擎在接受請求時: .識別符合SRV.11.2規(guī)則的web資源。 .如果一些filter是servlet和有servlet-name的web資源匹配的,引擎就會創(chuàng)建一個和描述文件中映射servlet-name的順序一樣的filter鏈。 .如果一些filter是rul-pattern關(guān)聯(lián)的,引擎就會創(chuàng)建一個和描述文件中映射url-pattern的順序一樣的efilter鏈。 一個高性能的web容器將會緩存filter鏈。 第七章 Sessions 超文本傳輸協(xié)議(HTTP)是無狀態(tài)的協(xié)議。要建立一個有效的web應(yīng)用,客戶端之間的通信是需要的。有很多會話跟蹤的策略, 但是直接使用這些技術(shù)都很難使用。servlet規(guī)范中提供了一個簡單的HttpSession接口,不需要開發(fā)者關(guān)心會話跟蹤的具體細節(jié)。 7.1 會話跟蹤機制 下面描述了幾種會話的跟蹤機制 7.1.1 Cookies HTTP cookies是最常用的會話跟蹤機制,所有的servlet引擎都應(yīng)該支持這種方法。 引擎發(fā)送一個cookie到客戶端,客戶端就會在以后的請求中把這個cookie返回給服務(wù)器。用戶會話跟蹤的cookie的名字必須是JSESSIONID 7.1.2 SSL Sessions 在安全套接字層,加密技術(shù)用在了HTTPS協(xié)議,從一個客戶端來的多個請求允許用一個含糊的標識,servlet引擎就用這個數(shù)據(jù)定義一個Session。 7.1.3 URL重寫 URL重寫是最低性能的通用會話跟蹤方法。當一個客戶端不能接受cookie時,URL重寫就會作為基本的會話跟蹤方法;URL重寫包括一個附加的數(shù)據(jù),一個session id,這樣的URL會被引擎解析和一個session相關(guān)聯(lián)。一個session id是作為URL的一個被編碼的參數(shù)傳輸?shù)?,這個參數(shù)名字必須是jsessionid.如下面的例子: 7.1.4 會話的完整性 一個web容器必須支持HTTP 會話。而當cookies方法不被支持時,通常使用URL重寫方法。 7.2 創(chuàng)建一個會話 servlet設(shè)計者必須考慮到一個客戶端不能加入session的情況。 7.3 會話范圍 HttpSession對象只在應(yīng)用程序級有效,通常用于session的cookie可以服務(wù)于不同的上下文,但一個HttpSession實例只服務(wù)于一個會話。舉個例子:如一個servlet A用RequestDispatcher去調(diào)用另一個web應(yīng)用中的另一個servlet B,用于A和B的會話一定是兩個不同的會話。 7.4 Session屬性的邦定 一個servlet可以通過一個name邦定一個對象到HttpSession實例中;只要獲得包含同一個會話的請求對象,任何邦定到會話中的對象在同一個ServletContext中對于其它的servlet都是可用的。 當把一個對象放入session或從session刪除時可能要通知其它對象,這些信息能夠被實現(xiàn)了HttpSessionBindingListener接口的對象獲得,這個接口定義了一下的一些方法。 valueBound valueUnbound valueBound方法在HttpSession接口調(diào)用getAttribute方法獲得一個有效的對象之前調(diào)用。valueUnbound方法在HttpSession接口調(diào)用getAttribute方法獲得一個不再有效的對象后調(diào)用。 7.5 會話超時 在HTTP協(xié)議中,當客戶端不再有效時,沒有清楚的定義終止信號。這就意味著通常只能采用時間超時來表明客戶端不再有效。 默認的超時時間是servlet引擎定義的,通過HttpSession的getMaxInactiveInterval方法可以得到超時的時間;開發(fā)者可用用setMaxInactiveInterval方法來設(shè)置超時的時間,以秒定義的。如果一個session的超時時間被設(shè)置為-1,則這個session將永遠有效。 7.6 最后訪問時間 在當前的請求中用HttpSession接口的getLastAccessedTime可以獲得最后一次訪問session的時間。 7.7 重要session  7.7.1 線程問題 在一個可以配置的應(yīng)用中,所有的請求都是一個會話的一部分,引擎一定能夠取出通過setAttribute或putValue放入HttpSession對象中的對象。注意以下的情況: .引擎一定能夠訪問實現(xiàn)了Serializable接口的對象。 .引擎可以選擇存儲HttpSession對象中指定的對象,如EJB組件和事務(wù)。 .引擎能夠監(jiān)聽到會話的變動。 如果放入session中的對象沒有被Seializable或沒有效,servlet可以拋出IllegalArgumentException;如果引擎不支持Session存儲對象的機制,引擎一定會拋出IllegalArgumentException。 這些限制意味著,在一個分布式引擎中,不會有額外的并發(fā)問題。 如果引擎為了service的品質(zhì)持續(xù)化或遷移session,使用本地持續(xù)化的HttpSession或它的屬性是不受限制的,開發(fā)者要想確保放入session中的屬性對象能夠可用,最好對象實現(xiàn)Serializable接口。 在遷移一個session時引擎必須通知session中實現(xiàn)了HttpSessinActivationListener的屬性對象,必須通知在序列化前鈍化的或序列化后激活的session的監(jiān)聽器。 開發(fā)分布式的開發(fā)者應(yīng)該清楚的是,一旦引擎運行在超過一個JVM的時候,就不能用static 表明變量來存儲應(yīng)用狀態(tài),應(yīng)該用EJB或數(shù)據(jù)庫賴存儲。 7.7.3客戶端  因為cookies或SSL證書都是被web瀏覽器訪問過程控制的,與任何特殊的window瀏覽器是沒有關(guān)系的。所以從所有window客戶端到一個servlet引擎的請求是同一個會話的一部分。最好是開發(fā)者總是設(shè)想所有的window客戶端是一起參與同一個會話的。 第八章 Dispatching Requests 當建立一個web應(yīng)用時,把一個請求傳給另一個servlet或在response中包含另一個servlet的輸出是經(jīng)常使用的。RequestDispatcher接口就提供了一些方法。 8.1 獲得RequestDispatcher 實現(xiàn)了接口RequesetDispatcher接口的對象可以在ServletContext的getRequestDispatcher或getNamedDispatchcer方法得到。 getRequestDispatcher的參數(shù)是一個以根目錄‘/’開始的一個路徑,該方法會查找路徑下的servlet,并把它封裝成RequestDispatchcer對象返回。 getNamedDispatcher方法把一個ServletContext知道的servlet名字作為參數(shù),如果找到servlet,該servlet就被封裝成RequestDispatcher對象返回,如果沒有找到則返回null。 RequestDispatcher對象中使用相對路徑也是可以的。在ServletRequest中提供了getRequestDispatcher方法;這個方法和ServletContext中同名的方法功能類似。servlet引擎會用request的信息把相對路徑轉(zhuǎn)化成完整路徑的。如ServleltRequest.getRequestDispatcher("header.html")和ServletConext.getRequestDispatcher("/garden/headere.html")是等效的。 8.1.1 在Request Dispatcher 路徑中附加字符串 在ServletContext和ServletRequest創(chuàng)建RequestDispatcher方法中參數(shù)都可以帶字符串如: Context.getRequestDispatcher("/raisons.jsp?orderno=5"); 8.2 Request Dispatcher的使用 對于使用Request Dispatcher 而言就是一個servlet調(diào)用include或forward方法,這些方法的參數(shù)是Servlet接口傳來的request和response對象實例。引擎必須確保調(diào)用Request Dispatcher的處理過程是在同一個JVM的同一個線程中。 8.3 include 方法 RequestDispatcher接口的include方法可以在任何時候被調(diào)用;目標servlet可以包含所有外的request對象,不過response對象的使用是有限制的: response只能寫信息到ServletOutputStream 或者Writer中,調(diào)用response對象的flushBuffer方法進行提交。不能夠設(shè)置頭信息,任何方法都不會影響到response的頭信息。 8.3.1 被包含的request參數(shù) 除了可以用getNamedDispatcher方法包含一個servlet外,以下的屬性可以被設(shè)置: Java.servlet.include.request_uri Java.servlet.include.context_path Java.servlet.include.servlet_path Java.servlet.include.path_info Java.servlet.include.query_string 用request對象的getAttribute方法可以獲取被包含servlet的以上屬性。 如果被包含的servlet能后通過getNamedDispatcher方法找到就不必設(shè)置以上屬性了。 8.4 Forward 方法 RequestDispatcher接口中的forward方法,只有servlet沒有提交響應(yīng)到客戶端時才可用;如果響應(yīng)buffer中有數(shù)據(jù)還沒有提交,當調(diào)用forward方法中目標servlet的service方法前,buffer中的內(nèi)容會被清空;如果buffer中的數(shù)據(jù)提交了,則發(fā)生IllegalStateException錯誤。 request對象的路徑必須放映獲取RequestDispatcher對象的路徑。 有個例外,如果RequestDispatcher是通過getNamedDispatcher方法得到的,request對象必須反映原始request的路徑。 在RequestDispatcher接口方法forward返回前,response的內(nèi)容必須被提交,并由引擎關(guān)閉該servlet。 8.4.1 query String 在Request Dispatcher中創(chuàng)建的路徑是可以帶參數(shù)的。 8.5 錯誤 如果request Dispatcher的目標servlet拋出運行時錯誤或ServletException 或IOException,錯誤就會被傳給調(diào)用的servlet;在上傳之到調(diào)用的servlet之前,所有其他的exception都應(yīng)該包裝成ServletExceptions。 第九章 web 應(yīng)用 一個web應(yīng)用是一堆servlet,html頁面,類和其他資源的集合。web應(yīng)用可以被發(fā)布運行在很多服務(wù)提供商的多種引擎下。 9.1 web服務(wù)器 在web服務(wù)中一個web應(yīng)用的根目錄是一個特殊的路徑,例如:一個網(wǎng)站目錄可以以http://www./登錄,所有的請求都將以這個作為前綴發(fā)送到以這個前綴描述的servletContext環(huán)境中。 在任何時候一個web應(yīng)用的實例只能運行在一個JVM中。 9.2 和servletContext的關(guān)系 servlet引擎會強迫web應(yīng)用和ServletContext的通信,一個ServletContext對象提供了一個servlet使得該應(yīng)用可見。 9.3 web應(yīng)用中的元素 一個web應(yīng)用包含以下的元素: .Servlets .JSP .Utility Classes .Static documents(html,images,sounds,etc) .Client side Java applets,beans,and classes .Descriptive meta informateion 9.4 部署層次 這個協(xié)議定義了一個層次結(jié)構(gòu),用于部署和打包,這個結(jié)構(gòu)存在于一個文件中。 9.5 目錄結(jié)構(gòu) 一個web應(yīng)用存在一個目錄層次結(jié)構(gòu)。文件根目錄是應(yīng)用的一部分。例如:一個web應(yīng)用的上下文路徑是/catalog,web應(yīng)用的index.html文件就能被/catalog/index.html請求訪問。URL和上下文路徑的匹配規(guī)則將在11章討論。servlet引擎必須拒絕一個具有現(xiàn)在沖突的上下文路徑的web應(yīng)用,這種情況是有的,如:兩個web應(yīng)用發(fā)布在同一個上下文路徑中,或一個web應(yīng)用的上下文路徑是另一個web應(yīng)用上下文路徑的子路徑。 有一個特殊的目錄(“WEB-INF”)在應(yīng)用中存在,這個目錄包含所有與應(yīng)用相關(guān),又不在根目錄中的事物??梢灾苯颖灰嫣峁┙o客戶端的文件不放在WEB-INF中,但WEB-INF目錄對于調(diào)用ServletContext的getResource和getResourceAsStream方法的servlet 代碼是有效的。如果開發(fā)者想用servlet代碼調(diào)用一個不希望暴露給客戶端的一個配置信息,就可以把這個配置信息放在WEB-INF目錄下。請求都是和資源相匹配的;敏感的匹配如客戶端的請求是“/WEB-INF/foo”和“/Web-iNf/foo”,但不應(yīng)該把定位于/WEB-INF下的內(nèi)容作為結(jié)果返回。 WEB-INF目錄下的內(nèi)容有: ./WEB-INF/web.xml 部署描述文件 ./WEB-INF/classes/ 存放servlet class ./WEB-INF/lib/*.jar 是jar包的目錄 應(yīng)用的classloader先load WEB-INF/classes目錄下的class后load WEB-INF/lib目錄下的jar包 9.5.1 目錄結(jié)構(gòu)的一個例子 一個簡單web應(yīng)用的目錄結(jié)構(gòu): /index.html /howto.jsp /images/banner.gif /images/jumping.gif /WEB-INF/web.xml /WEB-INF/lib/jspbean.jar /WEB-INF/classes/com/mycorp/servlets/MyServlet.class /WEB-INF/classes/com/util/MyUtils.class 9.6 web應(yīng)用的存檔文件 一個web應(yīng)用可以被java打包工具打包成war文件,當被打包后包中就會有一個額外META-INF目錄,該目錄下存放了打包工具的一些信息。 9.7 web應(yīng)用部署描述 下面是web應(yīng)用部署描述中的配置類型: .ServletContext Init Parameters .Session Configuration .Servlet / JSP Definitions .Servlet / JSP Mappings .MIME Type Mappings .Welcome File list .Error Pages .Security 9.7.1 可靠的擴展 web容器須提供一種機制使得web應(yīng)用知道jar文件中包含的有用資源或代碼。 引擎因該提供編輯、配置庫文件的程序。 在WAR中提供一個MANIFEST.MF文件,描述擴展名列表是比較好的。標準的JAR是應(yīng)該有的,這個文件描述的擴展名應(yīng)該遵循Http://java./j2se/1.3/docs/guide/extensions/versioning.html中的規(guī)定。web容器應(yīng)該能夠識別WEB-INF/lib文件夾中的任何文件的擴展名,如果不能夠識別就應(yīng)該拒絕該應(yīng)用程序,并報出錯誤。 9.7.2 web應(yīng)用的classloader 引擎用于裝載war中的servlet的裝載器必須能夠讓開發(fā)者裝載jar庫中的任何資源。但裝載的資源禁止覆蓋j2se或servlet API中的類;通常建議的做法是裝載器不允許war中的servlet去訪問web引擎中的類。 還有一個被推薦的做法是實現(xiàn)應(yīng)用類裝載器,war中被裝載的類或資源就會被放到container-wide JAR庫的特定類或資源中。 9.8 替換web應(yīng)用 一個服務(wù)器可能會在不重新啟動引擎的情況下用一個新版本的應(yīng)用替換原有的應(yīng)用。當一個應(yīng)用被替換時,引擎應(yīng)提供一個robust方法去保存該應(yīng)用中的session 9.9 錯誤句柄 9.9.1 request Attributes web應(yīng)用必須列出在使用中資源發(fā)生的錯誤,這些資源在部署描述中都有定義。 如果錯誤在一個servlet或一個jsp頁面中發(fā)生,則在第9.1章中的如下的請求屬性就會被設(shè)置: Request Attributes                               Type Javax.servlet.error.status_code       java.lang.Integer Javax.servlet.error.exception_type   java.lang.Class Javax.servlet.error.message            java.lang.String Javax.servlet.error.exception           java.lang.Throwable Javax.servlet.error.request_uri         java.lang.String Javax.servlet.error.servlet_name      java.lang.String 這些屬性允許這個servlet根據(jù)這些狀態(tài)碼、錯誤類型、錯誤信息、被拋出的錯誤對象、錯誤產(chǎn)生的servlet被訪問的URI(可以用getRequestURI得到)、或錯誤產(chǎn)生的servlet的邏輯名稱產(chǎn)生特殊的內(nèi)容。 在2.3版本中錯誤類型和錯誤信息屬性是多余的,他們被保留只是為了向下兼容以前的版本。 9.9.2 錯誤頁面 當一個servlet產(chǎn)生錯誤時,開發(fā)者可以訂制錯誤內(nèi)容返回給客戶端。部署描述文件定義了一個錯誤頁面列表。servlet在response中設(shè)置錯誤狀態(tài)碼或產(chǎn)生的異常或錯誤被引擎支持時,引擎就會從部署描述文件中調(diào)用相應(yīng)的配置的錯誤資源。 如果一個錯誤碼被設(shè)置在了response中,引擎在部署描述文件的錯誤頁面列表中用status-code方式匹配對應(yīng)的資源,如果找到就調(diào)用本地的資源。 在一個請求被處理的過程中servlet可以拋出以下的異常: .runtime exceptions or errors .ServletExceptions or subclasses thereof .IOException or subclasses thereof web應(yīng)用可以用exception-type元素來描述錯誤頁面,在這種情況下引擎會通過比較用exception-type元素定義的error-page列表中的異常來匹配產(chǎn)生的異常。匹配的結(jié)果是返回定義的與錯誤匹配的本地資源。在繼承類中,最近的類將被調(diào)用。 如果沒有一個error-page包含的exception-type與class-heirarchy相匹配。拋出的ServletException或其子類異常,被引擎通過ServletException.getRootCause方法獲得,獲得后用這個異常再去配置的error page列表中去匹配。 在部署描述文件中用exception-type元素定義的Error-page中exception-type的類名必須是唯一的。 當錯誤發(fā)生在servlet調(diào)用的RequestDispatcher中時error page機制是不能夠干預(yù)到的;這樣的情況如:一個servlet用RequestDispatcher去調(diào)用另一個有錯誤的servlet。 如果一個servlet產(chǎn)生的錯誤沒有被描述的錯誤頁面機制所抓到,引擎必須設(shè)置response的狀態(tài)碼為500 9.10 Welcome Files web應(yīng)用可以在部署描述文件中定義一個welcome files調(diào)用的URI列表,這個機制的目的是允許開發(fā)者定義自己的訪問首頁。 如果沒有在部署描述中配置welcome 文件,引擎將把局部請求(沒有指明具體訪問資源,如www.cacolg.com/index.html,請求訪問時用www.cacolg.com/訪問的)發(fā)送到適當?shù)馁Y源中,如:一個可能默認的servlet,或列出該目錄下的文件列表,或返回404響應(yīng)錯誤。 一個例子: 1)在部署描述中定義index.html和default.jsp為welcome files 2)定義一個servlet的mapping路徑為/foo/    WAR中有的文件如下:    /foo/index.html    /foo/default.html    /foo/orderform.html    /foo/home.gif    /catalog/default.jsp    /catalog/products/shop.jsp    /catalog/products/register.jsp 3)請求的URI為                    處理后的URI  /foo 或 /foo/                    /foo/index.html  /catalog/                        /catalog/default.jsp  /catalog/index.html           404 not found  /catalog/products/            404 not found 也可能返回shop.jsp and /or register.jsp 列表。 9.11 web應(yīng)用環(huán)境 j2EE定義的命名環(huán)境能夠使得應(yīng)用在不需要知道外部信息怎么命名的情況下比較方便的訪問資源或外部信息。 servlet作為j2EE完整的一部分,使web應(yīng)用部署描述文件提供了一個servlet可以訪問資源和EJB,這些部署描述元素有: .env-entry .ejb-ref .ejb-local-ref .resource-ref .resource-env-ref 開發(fā)者使用這些元素描述web應(yīng)用中需要用到的對象,這些對象都要在web容器運行時注冊到JNDI命名空間。 在J2EE1.3版本j2EE的環(huán)境需求中,servlet引擎不是J2EE技術(shù)的一部分,web環(huán)境要提供的功能在J2EE規(guī)范中有描述。如果沒有實現(xiàn)支持環(huán)境所要提供的功能,在發(fā)布應(yīng)用時,web容器就會拋出警告。 實現(xiàn)servlet引擎在J2EE中是需要的,應(yīng)該被納入J2EE1.3中。J2EE1.3應(yīng)該提供更多的內(nèi)容。 servlet引擎必須支持對象的lookup方法,查找對象并在引擎控制的線程中實例化。 servlet引擎應(yīng)該支持開發(fā)者創(chuàng)建的線程,因為應(yīng)用創(chuàng)建的線程不是很輕便,開開發(fā)者不得不依賴于這些功能有限的線程。這些需求將被加入到下一個版本的servlet規(guī)范中。 第十章 應(yīng)用周期事件 10.1 介紹 事件是servlet2.3種新添的內(nèi)容。應(yīng)用事件使得web開發(fā)者能夠控制ServletContext和HttpSession對象的信息交互,使得管理web使用的資源更有效,方便。 10.2 事件監(jiān)聽器 事件監(jiān)聽器是實現(xiàn)了servlet事件監(jiān)聽接口的類。在web發(fā)布是這些監(jiān)聽類就被實例化和注冊在web容器中。 servlet事件監(jiān)聽器提供了在ServletContext和HttpSerssion對象狀態(tài)發(fā)生改變時觸發(fā)的事件。Servlet cotext監(jiān)聽器用于管理應(yīng)用的資源或虛擬機的狀態(tài)。HTTP session監(jiān)聽器管理與會話關(guān)聯(lián)的資源。 可以有多個監(jiān)聽器監(jiān)聽每一個事件類型。開發(fā)者可以指定引擎調(diào)用監(jiān)聽類的順序。 10.2.1 事件類型和監(jiān)聽接口 Event Type                                 ListenerInterface                                 說明 Lifecycle                      javax.servlet.ServletContextListener              當servlet context被創(chuàng)建并有效的接受第一個請求                                                                                        或servlet context銷毀前 Changes to attributees   javax.servlet.ServletContextAttributesListener 當servlet context中的屬性發(fā)生added,removed,replaced Lifecycle                      javax.servlet.http.HttpSessionListener            當HttpSession被創(chuàng)建,無效或超時 Changes to attributes     javax.servlet.HttpSessionAttributesListener     當屬性added,removed或replaced時 10.2.2 一個使用監(jiān)聽的例子 一個簡單的web應(yīng)用中有servlet要訪問數(shù)據(jù)庫,開發(fā)者提供一個context 監(jiān)聽類管理數(shù)據(jù)庫連接。 1)web應(yīng)用啟動時,監(jiān)聽類被裝載,登陸數(shù)據(jù)庫,在servlet context中保存數(shù)據(jù)庫連接。 2)servlet訪問數(shù)據(jù)庫連接 3)當web服務(wù)銷毀時,或應(yīng)用從web服務(wù)中刪除時,關(guān)閉數(shù)據(jù)庫連接。 10.3 監(jiān)聽類的配置 10.3.1 對監(jiān)聽類的規(guī)定 web開發(fā)者提供實現(xiàn)了以上監(jiān)聽接口的類,每個類應(yīng)該有一個沒有參數(shù)的構(gòu)造器函數(shù)。監(jiān)聽類放在WEB-INF/classes下或以一個jar文件放在WEB-INF/lib下都可以。 10.3.2 部署描述 web容器對每個監(jiān)聽類只會創(chuàng)建一個實例,在第一個請求到來之前實例化并注冊。web容器注冊監(jiān)聽類的順序根據(jù)他們實現(xiàn)的接口和在部署描述文件中定義的順序。web應(yīng)用調(diào)用監(jiān)聽實例的順序按照他們注冊的順序。 10.3.4 在銷毀時的事件 當應(yīng)用銷毀時監(jiān)聽事件的執(zhí)行順序按部署描述中的順序,先執(zhí)行session中的監(jiān)聽事件再執(zhí)行context中的監(jiān)聽事件。session的無效事件必須在context的銷毀事件之前被調(diào)用。 10.4 部署描述的例子 下面給出注冊兩個servlet cocntext lifecycle監(jiān)聽器和一個HttpSession監(jiān)聽器的例子。 Com.acme.MyconnectionManager和com.acme.MyLoggingMoudule都實現(xiàn)了javax.servletServletContextListener接口,com.acme.MyloggingModule另外還實現(xiàn)了javax.servlet.HttpSessionListener接口。開發(fā)者希望com.acme.MyConnectionManager在com.acme.MyLoggingModule之前管理者servlet context 的生命周期事件。部署描述文件如下: <web-app>  <display-name>MyListeningApplication</display-name>  <listener>     <listener-class>com.acme.MyConnectionManager</listener-class>  </listenrer>  <listenrer>     <listenrer-class>com.acme.MyLoggingModele</listener-class>  </listener>  <sevlet>     <display-name>RegistrationServlet</display-name>     ..etc  </servlet> </web-app> 10.5 監(jiān)聽器的實例和線程 在第一個請求被web容器接受之前實例化并注冊好監(jiān)聽器類是必須的。監(jiān)聽器在整個web應(yīng)用生命周期中都要使用。 ServletContext和HttpSession對象屬性的改變可能會同時產(chǎn)生,引擎不需要同步這些屬性類的事件。 10.6 分布式容器組 在分布式web容器組中,HttpSession和ServletContext實例只活動與它們本地的JVM中。在分布式web容器中,監(jiān)聽實例會在每一個web容器中創(chuàng)建實例。 10.7 session事件  監(jiān)聽器使得開發(fā)者可以跟蹤web應(yīng)用中的session。知道session是否變得無效是經(jīng)常被用到的,因為session超時時引擎會使session變得無效,或應(yīng)用會調(diào)用invalidate方法。 第十一章 請求到servlet的映射 11.1 URI的使用 web容器根據(jù)客戶端的請求決定要調(diào)用的資源。 URL路徑映射規(guī)則是第一個匹配成功就不再匹配了。 1)引擎將盡力為每一個請求一個servlet的路徑匹配一個servlet 2)引擎將遞歸的匹配最長的路徑前綴(在一個目錄樹中) 3)如果在URL路徑中的最后一節(jié)有擴展名(例如:.jsp),則servlet引擎將會匹配一個適當?shù)膕ervlet獲取請求對象 4)如果沒有一個servlet能夠匹配請求,引擎將用一個適當?shù)馁Y源來處理該請求。如:在應(yīng)用中配置了默認的servlet,就會被用來處理匹配不到資源的請求。 11.2 匹配規(guī)則 在web應(yīng)用描述文件中,匹配的定義如下: .以‘/‘開始,以‘/*‘為結(jié)尾的字符串,用作路徑匹配 .以‘*.‘開始的字符串,用作擴展名匹配 .包含‘/‘字符串,定義一個默認的servlet。如匹配的servlet路徑是請求URI路徑的最小上下文路徑,路經(jīng)的info為空。 .其它的字符串用作精確的匹配。 11.2.1 絕對匹配 servlet引擎能夠匹配任何精確的資源,如后綴為*.jsp的匹配,引擎中有JSP引擎的話,就會把所有的JSP頁面和與之對象的資源相匹配。  11.2.2 匹配的例子:         path pattern                                servlet /foo/bar/*                                          servlet1 /baz/*                                               servlet2 /catalog                                             servlet3 *.bop                                                 servlet4         incoming path                             servlet handling request  /foo/bar/index.html                            servlet1  /foo/bar/index.bop                             servlet1  /baz                                                servlet2  /baz/index.html                                  servlet2  /catalog                                           servlet3  /catalog/racecar.bop                          servlet4  /index.bop                                        servlet4 第十二章 安全 12.1介紹 web應(yīng)用的資源能夠被很多的用戶訪問,這些資源經(jīng)常沒有保護的暴露在網(wǎng)絡(luò)中,因此一個穩(wěn)定的web應(yīng)用需要一個安全的環(huán)境。 提高安全性有以下的幾個方面: .認證:訪問一個實例前需要一個特殊的ID進行授權(quán)認證后才能訪問該實例 .資源的訪問控制:一些機密資源或局部資源只限制給某些用戶或程序使用。 .數(shù)據(jù)完整性:在傳輸過程中數(shù)據(jù)不能被意外的改變。 .機密性:確定信息只能被授權(quán)過的用戶使用。 12.2 公共安全 安全性聲明是指表明應(yīng)用是有安全結(jié)構(gòu)的;包括權(quán)限、訪問控制、認證。在web應(yīng)用中部署描述是安全聲明的主要工具。 開發(fā)者應(yīng)該為應(yīng)用運行時配一個邏輯安全策略,在運行時中,servlet引擎用這個安全策略去驗證授權(quán)請求。 安全模塊應(yīng)該適用web應(yīng)用的靜態(tài)內(nèi)容,當servlet用RequestDispatcher調(diào)用一個靜態(tài)資源或servlet用forward或include,時安全模塊不適用。 12.3 程序級安全 當應(yīng)用的安全模塊不能充分的表明安全時程序安全就可以被使用。 程序安全有以下部分組成: HttpServletRequest接口: .getRemoteUser .isUserInRole .getUserPrincipal getRemoteUser方法返回客戶端用戶的名稱,用于授權(quán)。 isUserInRole方法判斷遠程用戶是否在一個安全的角色內(nèi)。 getUserPrincipal方法返回一個java.security.Principal對象,表明當前用戶的主要名稱。這個API允許servlet根據(jù)這個信息處理一些業(yè)務(wù)邏輯。 如果用戶沒有授權(quán),getRemoteUser返回null,isUserInRole返回false,getUserPrincipal返回null。 isUserInRole以一個role-name為參數(shù)。一個security-role-ref元素為在部署描述文件中定義,role-name子元素包含角色名稱。Security-role包含一個子元素role-link,role-link的value值是客戶端用戶將匹配的安全角色。當用isUserInRole時引擎將調(diào)用security-role-ref到security-role的匹配。 舉個例子: <security-role-ref>  <role-name>FOO</role-name>  <role-link>manager</role-link> </security-role-ref> 當一個用戶屬于“manager”角色是調(diào)用isUsesrInRole("FOO")返回true 如果匹配一個security-role元素的security-role-ref沒有被定義,引擎必須找出一個與security-role列表不同的roel-name元素作為web應(yīng)用默認的安全角色。但默認的安全角色限制了變換角色名稱不需要重新編譯的機動性。 12.4 角色 一個安全角色是一組用戶的邏輯名稱。當應(yīng)用發(fā)布時,角色就部署在web應(yīng)用的運行時環(huán)境中了。在基于安全屬性的請求到來時,servlet引擎就會執(zhí)行公共安全或程序級安全。安全請求在以下的一些情況中會產(chǎn)生: 1)開發(fā)者給用戶群配置了一個安全角色。 2)開發(fā)者把一個安全角色配置給一個安全域中的一個主要名稱。 12.5 驗證 web客戶端可以用以下的一些機制驗證用戶: .HTTP Basic Authentication .HTTP Digest Authentication .HTTPS Client Authentication .Form Based Authentication 12.5.1 HTTP Basic Authentication HTTP Basic Authentication是基于用戶名和密碼的驗證機制,是在HTTP/1.0規(guī)范中定義的。web服務(wù)要求客戶端驗證用戶,web服務(wù)用一個realm字符串作為請求的一部分,用戶通過這個realm字符串被驗證。realm字符串不會和任何安全域相關(guān)聯(lián)??蛻舳双@得用戶名稱和密碼發(fā)送到服務(wù)端。然后服務(wù)端用一個特殊的realm去驗證該用戶。 Basic Authentication 不是安全的驗證協(xié)議。用戶的密碼是用base64編碼的,服務(wù)端是不能夠識別的。一些附加的安全措施可以被使用,這些協(xié)議有:HTTPS安全傳輸協(xié)議或網(wǎng)絡(luò)安全標準(如IPSEC協(xié)議、VPN策略)。 12.5.2 HTTP Digest Authentication 和HTTP Basic Authentication一樣,HTTP Digest Authentication 也是驗證用戶名和密碼的。然而這種驗證是把密碼加密傳輸?shù)模菳asic Authentication的base64編碼要安全的多。Digest Authentication 沒有被廣泛的運用,建議servlet引擎支持這種驗證,但不是必須的。 12.5.3 Form Based Authentication web應(yīng)用部署描述文件包含登陸表單和錯誤頁面。登陸表單必須包含用戶名和用戶密碼字段,這兩個字段必須以j_username和j_password命名。當一個用戶要訪問一個被保護的資源時,引擎就會驗證該用戶信息,如果該用戶驗證通過就會調(diào)用保護的資源,如果沒有驗證通過,以下的步驟就會發(fā)生: 1)登陸表單被送到客戶端,啟動這個驗證的URL路徑將被引擎保存。 2)用戶被要求填寫用戶名和密碼 3)客戶端重新post表單到服務(wù)端 4)引擎嘗試著重新去驗證該用戶的信息 5)如果驗證有失敗,響應(yīng)被設(shè)置為401的錯誤頁面將被返回 6)如果驗證成功,如果該訪問的資源在一個授權(quán)角色中,將進一步驗證。 7)如果用戶是授權(quán)用戶,客戶端將用保存的URL路徑重新定向到訪問的資源。 發(fā)送到驗證失敗的用戶的錯誤頁面包含了失敗的信息。 Form Based Authentication 和 Basic Authentication 有一樣的弊端,密碼是用簡單的文本傳輸?shù)模荒軌虮环?wù)端驗證。附加的一些協(xié)議可以增強這部分功能。如HTTPS傳輸協(xié)議,或網(wǎng)路安全標準(如IPSEC協(xié)議或VPN策略)。 12.5.3.1 登陸表單的一些注意事項 登陸的表單和跟蹤session的URL實現(xiàn)上是有限制的。 登陸表單只能在cookies或SSL跟蹤session的方式下才能使用。 登陸表單要進行驗證的話,表單的action就必須為j_security_check。這個約束使得登陸表單訪問的資源沒有問題,也避免了把表單外的字段提交進請求中。 在HTML頁面中登陸表單的一個例子如下: <form method="POST" action="j_security_check" >  <input type="text" name="j_username">  <input type="password" name="j_password"> </form> 當?shù)顷懕韱我驗?span>HTTP請求被調(diào)用時,原始的請求參數(shù)必須被引擎存儲,在驗證成功后重新定向請求的資源。 如果用登陸表單的用戶被驗證通過,創(chuàng)建了一個session,當session超時或調(diào)用了失效方法,使得登陸者推出了。后續(xù)來的請求就必須重新對用戶進行驗證。 12.5.4 HTTPS Client Authentication 用HTTPS驗證用戶是很強的驗證機制。這個驗證需要用戶擁有一個公共鑰匙(PKC)。servlet引擎不需要支持HTTPS協(xié)議。 12.6 驗證信息的跟蹤 基本的身份驗證實在運行時環(huán)境中進行的: 1)確認一個登陸驗證機制或策略已經(jīng)配置在web應(yīng)用中。 2)把需驗證的信息發(fā)往一個容器中的所有應(yīng)用。 3)當一個安全域被刪除時,用戶的請求就需要重新驗證。 第十三章 部署描述文件 13.1 部署描述元素 部署描述文件中的所有元素都要被所有的servlet引擎支持。配置類型有下面的幾種: .ServletContext Init Parameteres .Session Configuration .Servlet Declaration .Servlet Mapping .Application Lifecycle Listener classes .Filter Dfinitions and Filter Mappings .MIME Type Mappings .Error Pages 當servlet 引擎是實現(xiàn)了J2EE規(guī)范的一部分的時候,安全信息才有必要在部署描述文件中定義。 部署描述文件不光光只支持servlet規(guī)范,在部署描述文件為了適應(yīng)web應(yīng)用的需求增加了其他的部屬描述元素。如: .taglib .用于查找JNDI對象的一些元素(env-entry,ejb-ref,ejb-local-ref,resource-ref,resource-env-ref) 13.2 處理部屬描述文件的規(guī)則 本節(jié)主要講一下web容器訪問部屬描述文件的幾種規(guī)則。 .web容器應(yīng)該忽略部屬描述文件中數(shù)據(jù)的開始空字符和最后的空字符。 .web容器應(yīng)該有一個廣泛的選項用戶檢查web應(yīng)用的有效性。如檢查web應(yīng)用是否包含部署描述文件,部屬描述文件結(jié)構(gòu)是否正確。部署描述中應(yīng)該有語義檢查,如:安全規(guī)則有同樣的名字,應(yīng)該報錯等等。 .部署描述中的URI是假定在URL解碼表單中的 .引擎必須正確解釋部屬文件中的路徑,如:路徑‘/a/../b‘必須解釋為‘/b‘,因為路徑是以‘..‘開始的路徑在部署描述中是無效的。 .調(diào)用資源的URI與WAR的根目錄關(guān)聯(lián),以‘/’開頭 .在一個元素中,如果它的顯示值是一個列表,則這個列表將可能會報錯 13.2.1 DOCTYPE 所有2.3版本的部屬描述文件的DOCTYPE必須是: <!DOCTYPE web-app PUBLIC "-//sun Microsystems, inc.//DTD Web Application 2.3//EN" "http://java./dtd/web-app_2_3.dtd"> 13.3 DTD web應(yīng)用的部署描述文件DTD如下: <!--  web-app 元素是部署描述的根元素 --> <!ELEMENT web-app(icon?,display-name?,description?,distributable?,context-param*,filter*,filter-mapping*,listener*,servlet*,servlet-mapping*,session-config?,mime-mapping*,welcome-file-list?,error-page*,taglib*,resource-env-ref*,resource-ref*,security-constraint*,login-config?,security-role*,env-entry*,ejb-ref*,ejb-local-ref*)> <!-- Auth-constraint 元素定義了可以訪問資源列表的用戶角色。Role-name可以作為security-role元素的子元素出現(xiàn)也可以以role-name"*"出現(xiàn)表示所有的角色,如果*和role-name都出現(xiàn)了,引擎將解釋這個資源可以被所有角色使用。如果沒有定義角色,用戶就不能夠訪問定義的資源。 Used in :security-constraint --> <!ELEMENT auth-constraint (description?,role-name*)> <!-- Auth-method 元素是配置web應(yīng)用的安全機制的,是訪問被保護資源的先決條件。用戶必須用這個驗證機制驗證。這個元素Value值有“BASIC”,“DIGEST”,“FORM”或“CLIENT-CERT” Userd in : login-config --> <!ELEMENT auth-method(#PCDATA)> <!-- Context-param元素包含了servlet context初始化的參數(shù) Used in :web-app --> <!ELEMENT context-param(param-name,param-value,description?)> <!-- description元素用于對父元素進行說明,description元素可以包含任何說明信息。當父元素被工具訪問時這些說明就會顯示。 Used in :auth-contraint,context-param,ejb-local-ref,ejb-ref,env-entry,filter,init-param,resource-env-ref,resource-ref,ren-as,security-role,security-role-ref,servlet,user-data-constraint,web-app,web-resource-collection --> <!ELEMENT description(#PCDATA)> <!-- Display-name元素是一個簡稱,被調(diào)用的工具顯示,這個簡稱不必是唯一的 Used in: filter,security-constraint,sevlet,web-app 例如: <display-name>Employee self Service </display-name> --> <!ELEMENT display-name(#PCDATA)> <!-- Distributable 元素,這個元素出現(xiàn)在部署描述中,說明該應(yīng)用可以部署在分布式servlet引擎中。 Used in :web-app --> <!ELEMENT distributable EMPTY> <!-- Ejb-link 元素用在ejb-ref 或ejb-local-ref元素中,去指定EJB關(guān)聯(lián)的一個enterprise bean. Ejb-link中的名字是一個關(guān)聯(lián)著enterprise bean的路徑 或者是目標bean+一個以“#”開頭的路徑。一個ejb-name可以對應(yīng)多個enterprise beans。 Used in : ejb-local-ref,ejb-ref 例如: <ejb-link>EmployeeRecord</ejb-link> <ejb-link>../products/product.jar#ProductEJB</ejb-link> --> <!ELEMENT ejb-link (#PCDAATA)> <!--  ejb-local-ref 元素用于描述本地enterprise bean的home接口,描述由下面的部分組成: 一個可選的描述 與enterprise bean 相關(guān)的EJB名稱 Enterprise bean 的類型 Enterprise bean 的本地接口 可選的ejb-link信息 Used in: web-app --> <!ELEMENT ejb-local-ref (description?,ejb-ref-name,ejb-ref-type,local-home,local,ejb-link?)> <!-- Ejb-ref 元素用于描述enterprise bean的home接口。描述由下面組成: 一個可選描述 與enterprise bean 相關(guān)的EJB名稱 Enterprise bean 的類型 Enterprise bean 的本地接口 可選的ejb-link信息 Used in:web-app --> <!ELEMENT ejb-ref(description?,ejb-ref-name,ejb-ref,type,home,remote,ejb-link?)> <!-- Ejb-ref-name 元素包含一個EJB的名字,這個名字必須是唯一的;這個EJB是web應(yīng)用環(huán)境和關(guān)聯(lián)的java:comp/env context的入口。建議名字以“ejb/”開頭。 Used in : ejb-local-ref,ejb-ref 例如: <ejb-ref-name>ejb/Payroll</ejb-ref-name> --> <!ELEMENT ejb-ref-name(#PCDATA)> <!-- Ejb-ref-type 元素包含enterprise bean的類型。Ejb-ref-type元素必須是下面的一種: <ejb-ref-type>Entity</ejb-ref-type> <ejb-ref-type>Session</ejb-ref-type> Used in :ejb-local-ref,ejb-ref --> <!ELEMENT ejb-ref-type(#PCDATA)> <!-- Env-entry 元素包含了web應(yīng)用的環(huán)境入口的描述。描述包含一個可選的描述,一個環(huán)境入口的名稱,一個可選的value,如果value沒有被指定,在部署中必須提供。 --> <!ELEMENT env-entry (description?,env-entry-name,env-entry-value?,env-entry-type)> <!--  env-entry-name元素包含了web應(yīng)用環(huán)境入口的名稱,這個名稱是一個java:comp/env context關(guān)聯(lián)的JNDI名稱。名字必須是唯一的。 例如: <env-entry-name>minAmount</env-entry-name> Used in: env-entry --> <!ELEMENT env-entry-name(#PCDATA)> <!-- Env-entry-type 元素包含環(huán)境入口值的fully-qualified java類型,這是web應(yīng)用程序期望有的。 Env-enry-type合法的類型如下: Java.lang.Boolean Java.lang.Byte Java.lang.Character Java.lang.String Java.lang.Short Java.lang.Integer Java.lang.Long Java.lang.Float Java.lang.Double Used in : env-entry --> <!ELEMENT env-entry-type(#PCDATA)> <!-- Env-entry-value元素包含了web應(yīng)用環(huán)境入口的值,值必須是一個字符串。 例如: <env-entry-value>100.00</env-entry-value> Used in : env-entry <!ELEMENT env-entry-value(#PCDATA)> <!-- Error-code元素包含HTTP的一個錯誤代碼,如:404 Used in : error-page --> <!ELEMENT error-code(#PCDATA)> <!--  error-page 元素包含一個錯誤代碼映射或錯誤類型資源的一個路徑 Used in : web-app --> <!ELEMENT error-page((error-code | exception-type),location)> <!--  exception-type 包含一個java exception 類型的類名稱 Used in : error-page --> <!ELEMENT exception-type(#PCDATA)> <!--  extension元素包含一個擴展名。如“txt” Used in : mine-mapping --> <!ELEMENT extension (#PCDATA)> <!--  filter被filter-mapping中的一個servlet或一個URL通過filter-name映射。filter在運行時能夠通過FilterConfig接口訪問初始化的參數(shù)。 Used in : web-app --> <!ELEMENT filter (icon?,filter-name,display-name?,description?,filter-class,init-param*)> <!--  filter-class元素指明filter類. Used in :filter --> <!ELEMENT filtere-class(#PCDATA)> <!--  引擎用filter-mapping去匹配請求的URI以及匹配的順序,引擎在把匹配的URI匹配一個servlet。 Used in : web-app --> <!ELEMENT filter-mapping (Filter-name,(url-pattern | servlet-name))>  <!--  filtere-name元素表明了一個filter的邏輯名稱用于匹配用的。邏輯名稱必須唯一 Used in : filter,filere-mapping --> <!ELEMENT filter-name (#PCDATA)> <!--  form-error-page元素定義了當?shù)顷懯∈钦{(diào)用的頁面。這個路徑以“/”開始 Used in: form-login-config --> <!ELEMENT form-error-page (#PCDATA)> <!--  form-login-config元素指定了登陸的錯誤頁面,如果form不需要驗證,這個元素將被忽略。 Used in : login-config --> <!ELEMENT form-login-cofig (form-login-page,form-error-page)> <!--  form-login-page 元素定義了登陸的頁面。路徑以“/”開頭  used in :form-login-config --> <!ELEMENT form-login-page (#PCDATA)> <!--  home元素包含了enterprise bean的home接口的名稱 Used in :ejb-ref 例如: <home>com.aardvark.payroll.PayrollHome</home> <!ELEMENT home (#PCDATA)> <!--  http-method 包含了HTTP 方法(GET | POST |...) Used in:web-resource-collection --> <!ELEMENT http-method (#PCDATA)> <!--  icon 元素包含small-icon 和large-icon元素,指明一個gif或jpeg的圖標名稱 Used in : filter,servlet,web-app --> <!ELEMENT icon (small-icon?,large-icon?)> <!--  init-param元素包含了name/value的servlet的初始化參數(shù) Used in : filter,servlet --> <!ELEMETN init-param (param-name,param-value,description?)> <!--  jsp-file 元素 包含了一個以“/”開頭JSP文件的全名。 Used in : servlet --> <!ELEMENT jsp-file (#PCDATA)> <!--  large-icon 元素包含一個32*32的圖標文件名稱。圖片可以是jpeg或gif。  used in :icon 例如: <large-icon>employee-service-icon32*32.jsp</large-icon> --> <!ELEMENT large-icon (#PCDATA)> <!--  listener 元素對應(yīng)著listener bean Used in : web-app --> <!ELEMENT listener (listener-class)> <!--  listener-class 元素,元素值是監(jiān)聽類的類名。 Used in : listener --> <!ELEMENT listener-class (#PCDATA)> <!--  load-on-startup 元素指明了這個servlet在web啟動時是否必須裝入(調(diào)用servlet的init()方法)。這個內(nèi)容是可選的,但有值時必須是個整數(shù),如果是負數(shù),引擎可以選擇在任何時候裝載該servlet,如果是整數(shù)或0,引擎就必須在web應(yīng)用啟動時裝入該servlet。數(shù)字越小越被優(yōu)先裝入。如果值一樣,引擎可以自由選擇裝入的順序。 Used in : servlet --> <!ELEMENT load-on-startup (#PCDATA)> <!--  local元素包含了enterprise bean的local接口 Used in : ejb-local-ref --> <!ELEMENT local (#PCDATA)> <!--  local-home元素包含了enterprise bean的本地home接口 Used in : ejb-local-ref --> <!ELEMENT local-home (#PCDATA)> <!--  location 元素包含與web應(yīng)用根目錄關(guān)聯(lián)的資源,值必須以‘/’開頭 Used in : error-page --> <!ELEMENT location (#PCDATA)> <!--  login-config 元素用于配置驗證的方法的。 Used in :web-app --> <!ELEMENT login-conifg (auth-method?,realm-name?,form-login-config?)> <!--  mime-mapping 元素定義了擴展名和mime類型的映射關(guān)系。 Used in :web-app --> <!ELEMENT mime-mapping (extension,mime-type)> <!--  mime-type 元素包含了mime類型,如“text/plain” Used in : mime-mapping --> <!ELEMENT mime-type (#PCDATA)> <!--  param-name 元素包含參數(shù)的名稱,參數(shù)名必須唯一。 Used in : context-param,init-param --> <!ELEMENT param-name (#PCDATA)> <!--  param-value元素包含了參數(shù)的值 Used in : context-param,init-param --> <!ELEMENT param-value (#PCDATA)> <!--  realm-name 元素用于HTTP Basic 驗證中 Used in : login-config --> <!ELEMENT realm-name (#PCDATA)> <!--  remote 元素包含了enterprise bean 的remote接口 Used in : ejb-ref 例如:  <remote>com.wombat.empl.EmployeeService</remote> --> <!ELEMENT remote (#PCDATA)> <!--  res-auth 元素表明是web應(yīng)用代碼控制資源,還是引擎控制資源。該元素的值只能是以下的一種     <res-auth>Application</res-auth>     <res-auth>Container</res-auth> Used in : resource-ref --> <!ELEMENT res-auth (#PCDATA)> <!--  res-ref-name 元素指明了資源管理器(連接工廠)的名稱,這個名稱是和java:comp/env cocntext關(guān)聯(lián)的JNDI名稱。該名稱必須是唯一的。 Used in:resource-ref --> <!ELEMENT res-ref-name (#PCDATA)> <!--  res-sharing-scope 元素表明了從資源管理器連接工廠獲得的連接是否可以被共享。值必須是下面的一種:  <res-sharing-scope>Shareable</res-sharing-scope>  <res-sharing-scope>Unshareable</res-sharing-scope> 默認的值是Shareable Used in : resource-ref <!ELEMENT ref-sharing-scope (#PCDATA)> <!--  res-type 元素描述了資源的數(shù)據(jù)類型。 Used in : resource-ref --> <!ELEMENT res-type (#PCDATA)> <!--  resource-env-ref 元素描述了與web應(yīng)用管理對象相關(guān)的資源。包含一個可選的描述,一個資源環(huán)境名稱,一個環(huán)境資源類型。 Used in :web-app 例如: <resource-env-ref>  <resource-env-ref-name>jms/StockQueue</resource-env-ref-name>  <resource-env-type>javax.jms/Queue</resource-env-ref-type> </resource-env-ref> --> <!ELEMENT resource-env-ref (description?,resource-env-ref-name,resource-env-ref-type)> <!--  resource-env-ref-name元素一定一個環(huán)境資源名稱,這個名字是與java:comp/env context關(guān)聯(lián)的JNDI名稱,必須以唯一的。 Used in : resource-env-ref --> <!ELEMENT resource-env-ref-name (#PCDATA)> <!--  resource-env-ref-type元素定義了環(huán)境資源的類型,是一個java類或接口的全名。 Used in: resource-env-ref --> <!ELEMENT resource-env-ref-type (#PCDATA)> <!--    resource-ref 元素包含web應(yīng)用涉及的外部資源的描述。它有一個可選的描述,一個資源管理連接工廠的名稱,一個資源管理連接工廠的類型id,一個驗證類型(Application 或 Container),和一個可選的連接共享的選項(Shareale 或 Unshareable) Used in : web-app 例如: <resource-ref> <res-ref-name>jdbc/EmployeeApppDB</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> <res-sharing-scope>Shareable</res-sharing-scope> </resource-ref> --> <!ELEMENT resource-ref (description?,res-ref-name,res-type,res-auth,res-sharing-scope?)> <!--  role-link 元素是與安全角色相關(guān)的。Role-link元素必須包含一個在security-role元素中定義的安全角色的名稱。 Used in: security-role-ref --> <!ELEMENT role-link (#PCDATA)> <!--  role-name 元素包含一個安全角色的名稱,名稱必須遵守NMTOKEN規(guī)則。 Used in : auth-constraint,run-as,security-role,security-role-ref --> <!ELEMENT role-name (#PCDATA)> <!--  run-as 元素包含一個可選的描述,和一個安全角色的名稱。 Used in : servlet --> <!ELEMENT run-as (description?,role-name)> <!--  security-constraint元素用于安全約束與一個或多個web資源相關(guān)聯(lián)。 Used in :web-app --> <!ELEMENT security-constraint (display-name?,web-resource-collection+,auth-constraint?,user-data-constraint?)> <!--  security-role元素包含安全角色的定義,它由一個可選的安全角色的描述,一個安全角色名稱組成。 Used in : web-app 例如: <security-role> <description>    this role includes all employees who are authorized to access the employee service application. </description> <role-name>employee</role-name> </security-role> --> <!ELEMENT security-role (description?,role-name)> <!--  security-role-ref 元素包含一個可選的描述,一個調(diào)用代碼中的安全角色名稱,一個可選的安全角色連接。如果安全角色沒有被指定,開發(fā)者必須選擇一個適當?shù)陌踩巧_@個role-name元素的值必須是EJBConteext.isCallerInRole(String roleName)或HttpServletRequest.isUserInRole(String role)中的參數(shù)。 Used in :servlet --> <!ELEMENT security-role-ref (description?,role-name,role-link?)> <!--  servlet 元素包含一個servlet的數(shù)據(jù)描述。如果load-on-startup元素中指定了一個jsp文件,該JSP將被裝入。 Used in : web-app <!ELEMENT servlet (icon?,servlet-name,display-name?,description?,(servlet-class|jsp-file),init-param*,load-on-startup?,run-as?,security-role-ref*)> <!--  servlet-class元素包含一個全名的servlet類名稱。 Used in : servlet --> <!ELEMENT servlet-class (#PCDATA)> <!--  servlet-mapping元素定義了一個servlet和url的關(guān)聯(lián) Used in : web-app --> <!ELEMENT servlet-mapping (servlet-name,url-pattern)> <!--  servlet-name元素包含servlet的名稱,名稱是唯一的。 Used in : filter-mapping,servlet,servlet-mapping --> <!ELEMENT servlet-name (#PCDATA)> <!--  session-config 元素定義了session參數(shù) Used in : web-app --> <!ELEMENT session-config (session-timeout?)> <!--  session-timeout 元素定義了一個默認的會話超時的時間,使用于web應(yīng)用中的所有會話。時間必須是用分鐘的數(shù)值表示。 如果timeout是0或負數(shù),引擎將確保會話永遠不會超時。 Used in : session-config --> <!ELEMENT session-timeout (#PCDATA)> <!--  small-icon 元素包含一個16*16圖標文件的名稱。 Used in : icon 例如:  <small-icon>employee-service-icon16*16.jpg</small-icon> --> <!ELEMENT small-icon (#pCDATA)>  taglib 元素用于描述JSP tag 庫。 Used in : web-app --> <!ELEMENT taglib (taglib-uri,taglib-location)> <!--  taglib-location 元素包含一個資源定位,為tag庫找到tag描述文件 Used in:taglib --> <!ELEMENT taglib-location (#PCDATA)> <!--  taglib-uri元素描述了一個URI Used in: taglib --> <!ELEMENT taglib-uri (#PCDATA)> <!--  transport-guarantee元素指定了客戶端和服務(wù)端的通信關(guān)系,有NONE,INTEGRAL,CONFIDENTIAL。NONE表示著應(yīng)用不需要任何傳輸保障。INTEGRAL表示著在數(shù)據(jù)在客戶端到服務(wù)端的過程中不能有任何改變。CONFIDENTIAL表示在傳輸過程中防止其他傳輸內(nèi)容的干擾。在使用SSl時常用的就INTEGRAL或CONFIDENTIL。 Used in : user-data-constraint <!ELEMENT transport-guarantee (#PCDATA)> <!--  url-pattern 元素包含映射的url。必須符合11.2章中servlet API描述的規(guī)則。 Used in:filter-mapping,servlet-mapping,web-resource-collection --> <!ELEMENT url-pattern (#PCDATA)> <!--  user-data-constraint元素用于表明數(shù)據(jù)在客戶端到服務(wù)器端是怎么保護的。 Used in :security-constraint --> <!ELEMENT user-data-constraint (description?,transport-guarantee)> <!--  web-resource-collection元素用于web應(yīng)用中安全限制的資源被那些方法使用,如果沒有指定,就可以被web用的所有方法調(diào)用。 Used in:security-constraint --> <!ELEMENT web-resource-collection (web-resource-name,description?,url-pattern*,http-method*)> <!--  web-resource-name 包含一個web資源集合的名稱 Used in:web-resource-collection --> <!ELEMENT web-resource-name (#PCDATA)> <!--  welcome-file元素包含了web應(yīng)用中默認的訪問文件,如index.html Used in:welcome-file-list --> <!ELEMENT welcome-file (#PCDATA)> <!--  welcome-file-list包含welcome-file的列表 Used in:web-app --> <!ELEMENT welcome-file-list (welcome-file+)> <!--  ID機制可以增加額外的部署信息,不允許加一個非標準的元素到標準的部署描述中 --> <!ATTLIST auth-constraint id ID #IMPLIED> <!ATTLIST auth-method id ID #IMPLIED> <!ATTLIST context-param id ID #IMPLIED> <!ATTLIST description id ID #IMPLIED> <!ATTLIST display-name id ID #IMPLIED> <!ATTLIST ejb-link id ID #IMPLIED> <!ATTLIST ejb-local-ref id ID #IMPLIED> <!ATTLIST ejb-ref  id ID #IMPLIED> <!ATTLIST ejb-ref-name id ID #IMPLIED> <!ATTLIST ejb-ref-type id ID #IMPLIED> <!ATTLIST env-entry id ID #IMPLIED> <!ATTLIST env-entry-name id ID #IMPLIED> <!ATTLIST env-entry-type id ID #IMPLIED> <!ATTLIST env-enry-value id ID #IMPLIED> <!ATTLIST error-code id ID #IMPLIED> <!ATTLIST error-page id ID #IMPLIED> <!ATTLIST exception-type id ID #IMPLIED> <!ATTLIST extension id ID #IMPLIED> <!ATTLIST filter id ID #IMPLIED> <!ATTLIST filter-class id ID #IMPLIED> <!ATTLIST filtere-mapping id ID #IMPLIED> <!ATTLIST filter-name id ID #IMPLIED> <!ATTLIST form-error-page id ID #IMPLIED> <!ATTLIST form-login-config id ID #IMPLIED> <!ATTLIST form-login-page id ID #IMPLIED> <!ATTLIST home id ID #IMPLIED> <!ATTLIST http-method id ID #IMPLIED> <!ATTLIST icon id ID #IMPLIED> <!ATTLIST init-param id ID #IMPLIED> <!ATTLIST jsp-file id ID #IMPLIED> <!ATTLIST large-icon id ID #IMPLIED> <!ATTLIST listener id ID #IMPLIED> <!ATTLIST listener-class id ID #IMPLIED> <!ATTLIST load-on-startup id ID #IMPLIED> <!ATTLIST local id ID #IMPLIED> <!ATTLIST local-home id ID #IMPLIED> <!ATTLIST location id ID #IMPLIED> <!ATTLIST login-config id ID #IMPLIED> <!ATTLIST mime-mapping id ID #IMPLIED> <!ATTLIST mime-type id ID #IMPLIED> <!ATTLIST param-name id ID #IMPLIED> <!ATTLIST param-value id ID #IMPLIED> <!ATTLIST realm-name id ID #IMPLIED> <!ATTLIST remote id ID #IMPLIED> <!ATTLIST res-auth id ID #IMPLIED> <!ATTLIST res-ref-name id ID #IMPLIED> <!ATTLIST res-sharing-scope id ID #IMPLIED> <!ATTLIST res-type id ID #IMPLIED> <!ATTLIST resource-env-ref id ID #IMPLIED> <!ATTLIST resource-env-ref-name id ID #IMPLIED> <!ATTLIST resource-env-ref-type id ID #IMPLIED> <!ATTLIST resource-ref id ID #IMPLIED> <!ATTLIST role-link id ID #IMPLIED> <!ATTLIST role-name id ID #IMPLIED> <!ATTLIST run-as id ID #IMPLIED> <!ATTLIST security-constraint id ID #IMPLIED> <!ATTLIST security-role id ID #IMPLIED> <!ATTLIST security-role-ref id ID #IMPLIED> <!ATTLIST sevlet id ID #IMPLIED> <!ATTLIST servlet-class id ID #IMPLIED> <!ATTLIST servlet-mapping id ID #IMPLIED> <!ATTLIST servlet-name id ID #IMPLIED> <!ATTLIST session-config id ID #IMPLIED> <!ATTLIST session-timeout id ID #IMPLIED> <!ATTLIST small-icon id ID #IMPLIED> <!ATTLIST taglib id ID #IMPLIED> <!ATTLIST taglib-location id ID #IMPLIED> <!ATTLIST taglib-uri id ID #IMPLIED> <!ATTLIST transport-guarantee id ID #IMPLIED> <!ATTLIST rul-pattern id ID #IMPLIED> <!ATTLIST user-data-constraint id ID #IMPLIED> <!ATTLIST web-app id ID #IMPLIED> <!ATTLIST web-resource-collection id ID #IMPLIED> <!ATTLIST web-resource-name id ID #IMPLIED> <!ATTLIST welcome-file id ID #IMPLIED> <!ATTLIST welcome-file-list id ID #IMPLIED> 13.4 例子 13.4.1 基本的例子 <!DOCTYPE web-app PUBLIC "-//Sun Mmicrosystems, Inc.//DTD Web Application 2.3//EN" "http://java./j2ee/dtds/web-app_2_3.dtd"> <web-app>     <display-name>A Simple Application</display-name>     <context-param>         <param-name>Webmaster</param-name>         <param-value>webmaster@</param-value>    </context-param>     <servlet>         <servlet-name>catalog</servlet-name>         <serrvlet-class>com.mycorp.Catalogservlet</servlet-class>         <init-param>             <param-name>catalog</param-name>             <param-value>Spring</param-value>         </init-param>     </servlet>     <servlet-mapping>         <servlet-name>catalog</servlet-name>         <url-pattern>/catalog/*</url-pattern>     </servlet-mapping>     <session-config>         <session-timeout>30</session-timeout>     </session-config>     <mime-mapping>         <extension>pdf</extension>         <mime-type>application/pdf</mime-type>     </mime-mapping>     <welcome-file-list>         <welcome-file>index.jsp</welcome-file>         <welcome-file>index.html</welcome-file>         <welcome-file>index.htm</welcome-file>     </welcome-file-list>     <error-page>         <error-code>404</error-code>         <location>/404.html</location>     <error-page> </web-app> 13.4.2 一個安全的例子 <!DOCTYPE web-app PUBLIC "-//Sun Mmicrosystems, Inc.//DTD Web Application 2.3//EN" "http://java./j2ee/dtds/web-app_2_3.dtd"> <web-app>     <display-name>A Secure Application</display-name>     <security-role>         <role-name>manager</role-name>     </security-role>     <servlet>         <servlet-name>catalog</servlet-name>         <servlet-class>com.mycorp.CatalogServlet</servlet-class>         <init-param>             <param-name>catalog</param-name>             <param-value>Spring</param-value>         </init-param>         <security-role-ref>              <role-name>MGR</role-name>              <!-- 在代碼中用的角色名稱-->              <role-link>manager</role-link>         </security-role-ref>     </servlet>     <servlet-mapping>          <servlet-name>catalog</servlet-name>          <url-pattern>/catalog/*</url-pattern>     </servlet-mapping>     <security-constraint>         <web-resource-collection>             <web-resource-name>SalesInfo</web-resource-name>             <url-pattern>/salesinfo/*</url-pattern>             <http-method>GET</http-method>             <http-method>POST</http-method>         </web-resource-collection>         <auth-constraint>             <role-name>manager</role-name>         </auth-constraint>         <user-data-constraint>             <transport-guarantee>CONFIDENTIAL</transport-guarantee>         </user-data-constraint>     </security-constraint> </web-app> 結(jié)尾: servlet2.3到此就結(jié)束了,至于對接口類的解釋。這里就不給與了。有興趣的朋友可以down一個servlet2.3的源碼包自己研究研究。 Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1362756 | 
|  | 
來自: jianjun0921 > 《servlet》