Servlet Context
1. ServletContext接口介紹
ServletContext接口定義了運行著該servlet的Web應(yīng)用程序的servlet視圖。容器提供者負責(zé)提供servlet容器中的ServletContext接口的實現(xiàn)。使用ServletContext對象,servlet可以記錄事件,獲取對資源的URL引用,并設(shè)置和存儲上下文中的其他servlet可以訪問的屬性。ServletContext植根于Web服務(wù)器中的已知路徑。例如,一個servlet上下文可能位于http://example.com/catalog。 所有以/catalog請求路徑開頭的請求(稱為上下文路徑)都被路由到與ServletContext關(guān)聯(lián)的Web應(yīng)用程序。
2.ServletContext接口的作用域
與部署到容器中的每個Web應(yīng)用程序相關(guān)聯(lián)的ServletContext接口有一個實例對象。在容器分布于許多虛擬機的情況下,Web應(yīng)用程序?qū)槊總€JVM提供ServletContext的實例。
容器中的未作為Web應(yīng)用程序的一部分部署的servlet是“缺省”Web應(yīng)用程序的隱式部分,并且具有默認的ServletContext。在分布式容器中,默認的ServletContext是不可分配的,并且必須只存在于一個JVM中。
3.初始化參數(shù)
ServletContext接口的以下方法允許servlet訪問與應(yīng)用程序開發(fā)人員在部署描述符中指定的Web應(yīng)用程序相關(guān)的上下文初始化參數(shù):
getInitParameter
getInitParameterNames
應(yīng)用程序開發(fā)人員使用初始化參數(shù)來傳遞設(shè)置信息。典型的例子是一個站長的電子郵件地址,或者一個擁有重要數(shù)據(jù)的系統(tǒng)的名字。
4. 配置方法
自Servlet 3.0啟用了Servlet、過濾器和它們映射到的url模式的編程定義,所以以下方法被添加到ServletContext中。這些方法只能在應(yīng)用程序從 ServletContextListener實現(xiàn)的contexInitialized方法或從 ServletContainerInitializer實現(xiàn)的onStartup方法的初始化期間被調(diào)用。除了添加Servlet和過濾器之外,還可以查找與Servlet或過濾器對應(yīng)的注冊對象的實例,或為Servlet或過濾器的所有注冊對象的映射。如果ServletContext傳遞到ServletContextListener的contextInitialized方法中,但是ServletContextListener在web.xml或web-fragment.xml中沒有被聲明,也沒有被注解@WebListener,那么在ServletContext中所定義的對于servlet、篩選器和監(jiān)聽器的編程配置的所有方法,都必須拋出UnsupportedOperationException。
4.1 編碼添加和配置servlet
The ability to programmatically add a servlet to a context is useful for framework developers. For example a framework could declare a controller servlet using this method. The return value of this method is a ServletRegistration or a ServletRegistration.Dynamic object which further allows you to setup the other parameters of the servlet like init-params, url-mappings etc. There are three overloaded versions of the method as described below.
以編程方式向上下文添加servlet的能力對框架開發(fā)人員非常有用。例如,一個框架可以使用這個方法聲明一個控制器servlet。此方法的返回值為ServletRegistration或ServletRegistration。動態(tài)對象進一步允許您設(shè)置servlet的其他參數(shù),如init-params、url映射等。
- addServlet(String servletName, String className)
該方法允許應(yīng)用程序以編程方式聲明servlet。它使用給定的名稱添加servlet,并將類名添加到servlet上下文。
addServlet(String servletName, Servlet servlet)
該方法允許應(yīng)用程序以編程方式聲明servlet。它使用給定的名稱添加servlet,并將servlet實例添加到servlet上下文。addServlet(String servletName, Class <? extends Servlet>
servletClass)
該方法允許應(yīng)用程序以編程方式聲明servlet。它使用給定的名稱添加servlet,并將servlet類的實例添加到servlet上下文。addJspFile(String servletName, String jspfile)
該方法允許應(yīng)用程序以編程方式聲明jsp。它將jsp添加到給定的名稱,并將servlet類的實例與servlet上下文對應(yīng)起來。<T extends Servlet> T createServlet(Class<T> clazz)
該方法實例化給定的Servlet類。該方法必須支持所有適用于servlet的注解,除了@WebServlet。返回的Servlet實例可以通過調(diào)用addServlet(String, Servlet),在ServletContext注冊之前進一步定制。ServletRegistration getServletRegistration(String servletName)
該方法返回對應(yīng)于給定名稱的servlet的ServletRegistration,如果該名稱下不存在ServletRegistration,則返回null。如果ServletContext傳遞到未在web.xml和web-fragment.xml中定義且j沒有注解avax.servlet.annotation.WebListener注釋的ServletContextListener的contextInitialized方法,將拋出UnsupportedOperationException。
- Map<String, ? extends ServletRegistration> getServletRegistrations()
該方法返回一個ServletRegistration對象的映射,該映射由與ServletContext注冊的所有servlet對應(yīng)的名稱鍵入。如果沒有在ServletContext注冊的servlet,則返回空映射。返回的映射包括與所有聲明的和帶注釋的servlet對應(yīng)的ServletRegistration對象,以及與通過一個addServlet和addJspFile方法添加的所有servlet對應(yīng)的ServletRegistration對象。返回的映射的任何更改都不應(yīng)影響ServletContext。如果ServletContext傳遞到未在web.xml和web-fragment.xml中定義且j沒有注解avax.servlet.annotation.WebListener注釋的ServletContextListener的contextInitialized方法,將拋出UnsupportedOperationException。
4.2 編碼添加和配置filter
4.3 編碼添加和配置監(jiān)聽器
4.4 編碼配置session超時時間
4.5 編碼配置字符集編碼
5.Context屬性
servlet可以通過名稱將對象屬性綁定到上下文。綁定到上下文的任何屬性都可用于同一Web應(yīng)用程序的任何其他servlet。下面的ServletContext接口方法允許訪問這個功能:
- setAttribute
- getAttribute
- getAttributeNames
- removeAttribute
5.1 Context Attributes in a Distributed Container
上下文屬性是創(chuàng)建它們的JVM的本地屬性。這將防止ServletContext屬性成為分布式容器中的共享內(nèi)存存儲。當(dāng)servlet之間需要共享的信息運行在分布式環(huán)境中,信息應(yīng)該放在一個會話(見第七章“會話”),存儲在數(shù)據(jù)庫中,或設(shè)置在一個Enterprise javabean?組件。
6. Resources
ServletContext接口只提供了靜態(tài)內(nèi)容文檔的層次結(jié)構(gòu),這些文檔是Web應(yīng)用程序的一部分,包括HTML、GIF和JPEG文件,通過ServletContext接口的下列方法:
- getResource
- getResourceAsStream
getResource和getresour流方法以一個字符串作為參數(shù),它提供了相對于上下文的根的資源的路徑,或者相對于web應(yīng)用程序的 WEB-INF/lib目錄中的JAR文件的META-INF/resources目錄。如果在WEB-INF/lib中的一個JAR文件的META-INF/resources條目中有一個WEB-INF條目,那么它和所有子條目只能作為靜態(tài)資源可用。從這樣的WEB-INF條目中不會將類或jar放在上下文類路徑上,也不會處理Servlet特定的描述符。在查看web-inf/lib目錄中的任何JAR文件之前,這些方法將首先搜索web應(yīng)用程序上下文的根。在WEB-INF/lib目錄中JAR文件的順序是未定義的。這種層次的文檔可能存在于服務(wù)器的文件系統(tǒng)中,在Web應(yīng)用程序存檔文件中,在遠程服務(wù)器上,或者在其他位置。
這些方法不用于獲取動態(tài)內(nèi)容。例如,在一個支持JavaServer Pages?specification1的容器中,一個以getResource("/index.jsp")的形式方法調(diào)用將返回JSP源代碼,而不是處理輸出。有關(guān)訪問動態(tài)內(nèi)容的更多信息,請參見第9章“調(diào)度請求”。
可以使用getResourcePaths(String path)方法訪問Web應(yīng)用程序中資源的完整列表。在本規(guī)范的API文檔中可以找到該方法的語義的完整細節(jié)。
7. 多個主機和Servlet上下文
Web服務(wù)器可以支持在服務(wù)器上共享一個IP地址的多個邏輯主機。這種能力有時被稱為“虛擬主機”。在這種情況下,每個邏輯主機必須有自己的servlet上下文或servlet上下文集。不能在虛擬主機之間共享Servlet上下文。
ServletContext接口的getVirtualServerName方法允許訪問部署ServletContext的邏輯主機的配置名稱。Servlet容器可能支持多個邏輯主機。此方法必須為部署在邏輯主機上的所有servlet上下文返回相同的名稱,并且該方法返回的名稱必須是不同的、穩(wěn)定的每個邏輯主機,并且適合于將服務(wù)器配置信息與邏輯主機關(guān)聯(lián)起來。
8.重新加載注意事項
雖然不需要一個容器提供程序來實現(xiàn)類重載方案,但是任何這樣的實現(xiàn)都必須確保所有的servlet和它們可能使用的類都被加載到一個類裝入器的范圍內(nèi)。需要這樣的需求來保證應(yīng)用程序的行為符合開發(fā)人員的期望。作為一個開發(fā)輔助工具,通知到會話綁定偵聽器的完整語義應(yīng)該由容器來支持,以便在類重載時的會話終止監(jiān)視中使用。
前幾代容器創(chuàng)建了新的類裝入器來加載servlet,這與用于裝載servlet上下文中的其他servlet或類的類加載器截然不同。這可能導(dǎo)致servlet上下文中的對象引用指向意外的類或?qū)ο?,并?dǎo)致意外的行為。該需求是為了防止新類裝入器的需求生成所引起的問題。
8.1 臨時工作目錄
每個servlet上下文都需要一個臨時存儲目錄。Servlet容器必須為每個Servlet上下文提供一個私有臨時目錄,并通過javax.servlet.context.tempdir上下文屬性提供它。與該屬性關(guān)聯(lián)的對象必須是java.io.File類型的。
該需求識別了許多servlet引擎實現(xiàn)中提供的公共便利。當(dāng)servlet容器重新啟動時,容器并不需要維護臨時目錄的內(nèi)容,但是需要確保一個servlet上下文的臨時目錄的內(nèi)容對運行在servlet容器上的其他Web應(yīng)用程序的servlet上下文不可見。