第四章 Servlet上下文(JavaTM Servlet 规范3.1 )

Servlet Context Servlet 上下文)

 

4.1  Introduction to the ServletContext Interfacen ServletContext接口介绍

ServletContext 接口定义了运行在Web应用中的 servlet 的视图。容器提供者有义务提供在此 servlet 容器中 ServletContext 接口的一个实现。利用 ServletContext 对象,servlet 可以记录事件,获取资源的URL引用,设置和存储在此上下文中其它 Servlets 可以访问的属性。

 

4.2     ServletContext 接口的作用域

每一个部署到容器中的Web应用都有一个与之关联的 ServletContext 接口的实例对象。在容器被部署到多个虚拟机的情况下,对每一个JVM,Web 应用都有一个 ServletContext 的实例。

容器中没有被作为Web应用的一部分部署的 Servlets ,会隐含的作为“默认” Web应用的一部分并且有一个默认 ServletContext 。在一个分布式容器中,默认ServeletContext 是非分布式的并且只能存在于一个JVM中。

 

4.3     初始化参数

下面的 ServletContext 接口方法允许 servlet 访问应用开发者在部署描述符中指定的与Web应用关联的上下文初始化参数:

  • getInitParameter
  • getInitParamertNames

初始化参数被应用开发者描述配置信息。典型的例子是网管的email地址,或者一个持有关键数据的系统的名称。

 

4.4     配置方法

下面的方法从 Servlet 3.0 开始添加到 ServletContext ,以便可以编程式定义 servlets,filters 和映射他们的 Url 匹配。这些方法只能在应用的初始化期间被调用,要么是 ServletContextListener 实现的 contexInitialized 方法,要么是ServletContainerInitializer 实现的 onStartup 方法。除了添加 Servlets 和 Filters,还能查询与一个 Servlet 或者 Filter 对应的 Registration 对象实例,或者 servlets 或 filters 对应的所有 Registration 对象的Map。如果 ServletContext 传递给既没有在web.xml 或 web-fragment.xml中声明又没有@WebListener 注解的 ServletContextListener 的 contextInitialized 方法 ,在 ServletContext 中定义的用来编程式配置 servlets ,filters 和 listeners 的所有方法必须抛出 UnsupportedOperationException 异常。

4.4.1 编程式添加和配置 Servlets

对框架开发者来说能通过编程式添加一个 servlet 到给 context 是很有用的。例如,框架可以使用这个方法声明一个控制器 servlet。这个方法的返回值是一个ServletRegistration 或 ServletRegistration.Dynamic 对象,它允许你进一步设置这个 servlet 的其他参数,比如 init-params, url-mappings 等。这个方法有三个如下描述的重载版本:

 

4.4.1.1          addServlet(String servletName, String className)

这个方法允许应用编程式声明一个servlet。它用给定的名字和类名添加 servlet 到 servlet 上下文。


4.4.1.2          addServlet(String servletName, Servlet servlet)

这个方法允许应用编程式声明一个servlet。它用给定的名字和 servlet 实例添加 servlet 到 servlet 上下文。


4.4.1.3         addServlet(String servletName, Class <? extends Servlet> servletClass)

这个方法允许应用编程式声明一个servlet。它用给定的名字和一个 servlet 类的实例添加 servlet 到 servlet 上下文。

4.4.1.4         <T extends Servlet> T createServlet(Class<T> clazz) 



这个方法实例化给定的 Servlet 类。 这个方法必须支持适用于 Servlet 的除了 @WebServlet 以外的所有注解。返回的 Servlet 实例通过调用前面定义的 addServlet(String,Servlet)注册到 ServletContext之前可以进一步定制。

4.4.1.5         ServletRegistration getServletRegistration(String servletName) 


这个方法返回与给定名称对应的 servlet 的ServletRegistration,如果此名称下不存在 ServletRegistration 将返回 null。如果此 ServletContext  传递给一个既没有在 web.xml 或 web-framgment.xml 中声明又没有 @WebListener 注解的 ServletContextListener 的 contextInitialized 方法时,将会抛出UnsupportedOperationException异常。

4.4.1.6          Map<String, ? extends ServletRegistration>

该方法返回 ServletRegistration 对象的一个map,键名对应着在 ServletContext 中注册的所有 sevlets 的名称。如果此ServletContext中没有注册 servlets 那么返回空 map。返回的 map 包含所有声明和注解的 servlets 对应的 ServletRegistration 对象,也包括通过 addServlet 方法添加的所有 servlets 对应的 ServletRegistration 对象。返回的 Map 的任何变化不能影响 ServletContext。如果此 ServletContext 传递给一个既没有在 web.xml 或 web-framgment.xml 中声明又没有 @WebListener 注解的 ServletContextListener 的 contextInitialized 方法时,将会抛出 UnsupportedOperationException 异常。

4.4.2 Programmatically adding and configuring Filters 编程式添加和配置Filters

4.4.2.1  addFilter(String filterName, String className) 



此方法允许应用编程式声明一个 filter。它用给定的名称和类名添加一个 filter 到 web 应用。

4.4.2.2  addFilter(String filterName, Filter filter) 
 


该方法允许应用编程式声明一个 filter。它用给定的名称和 filter 实例添加一个 filter 到 web 应用。

4.4.2.3  addFilter(String filterName, Class <? extends Filter> filterClass) 
 


该方法允许应用编程式声明一个 filter。它用给定的名称和 filter 类的实例添加一个 filter 到 web 应用。

4.4.2.4  <T extends Filter> T createFilter(Class<T> clazz) 


该方法实例化一个给定的Filter类。该方法必须支持所有适用于 Fitlers 的所有注解。在将返回的Filter实例通过前面定义的 addFilter(String,Filter) 注册到 ServletContext 之前可以做进一步的定制。给定的Filter类必须定义一个无参构造方法用来实例化它。


4.4.2.5  FilterRegistration getFilterRegistration(String filterName) 


该方法用来返回与给定名称的 Filter 对应的 FilterRegistration,如果该名称下没有 FilterRegistration 将会返回 null。如果此 ServletContext 传递给一个既没有在 web.xml 或 web-framgment.xml 中声明又没有 @WebListener 注解的 ServletContextListener 的 contextInitialized 方法时,将会抛出 UnsupportedOperationException 异常。

4.4.2.6  Map<String, ? extends FilterRegistration> getFilterRegistrations() 



该方法返回 FilterRegistration 对象的一个 map,键名对应着在 ServletContext 中注册的所有 filters 的名称。如果此 ServletContext 中没有注册 filters 那么返回空 map。返回的 map 包含所有声明和注解的 filters 对应的 FilterRegistration 对象,也包括通过 addFilter 方法添加的所有 filters 对应的 FilterRegistration 对象。返回的 Map 的任何变化不能影响 ServletContext。如果此 ServletContext 传递给一个既没有在 web.xml 或 web-framgment.xml 中声明又没有@WebListener 注解的 ServletContextListener 的 contextInitialized 方法时,将会抛出 UnsupportedOperationException 异常。

4.4.3 Programmatically adding and configuring Listeners 编程式添加和配置Listeners

4.4.3.1  void addListener(String className) 


添加指定类名的 listener 到 ServletContext。给定名字的类使用代表应用的 ServletContext 关联的加载器加载,并且必须实现下面的一个或者多个接口:


■ javax.servlet.ServletContextAttributeListener

■ javax.servlet.ServletRequestListener


■ javax.servlet.ServletRequestAttributeListener

■ javax.servlet.http.HttpSessionListener 


■ javax.servlet.http.HttpSessionAttributeListener

■ javax.servlet.http.HttpSessionIdListener

如果 ServletContext 传递给了 ServletContainerInitializer 的 onStartup 方法,那么给定名称的类除了实现上面列出的接口之外,也可以实现ServletContextListener。作为这个方法调用的一部分,容器必须使用指定的类名加载类以确保它实现了需要的接口之一。如果给定名称的类实现了一个 listener 接口,它的调用顺序对应着声明顺序,也就是说,如果它实现了ServletRequestListener,ServletContextListener 或 HttpSessionListener,那么这个新的 listener 将被添加到那个接口的 listeners 的有序列表末尾。


4.4.3.2  <T extends EventListener> void addListener(T t)

添加给定的 listener 到 ServletContext。这个给定的 listener 必须是下列一个或多个接口的实例:


■ javax.servlet.ServletContextAttributeListener

■ javax.servlet.ServletRequestListener


■ javax.servlet.ServletRequestAttributeListener

■ javax.servlet.http.HttpSessionListener 


■ javax.servlet.http.HttpSessionAttributeListener

■ javax.servlet.http.HttpSessionIdListener 


如果 ServletContext 传递给 ServletContainerInitializer 的 onStartup 方法,那么给定的 listener 可以是上面列出的接口的实例,也可以是 ServletContextListener 的实例。如果给定的 listener 是一个 listener 接口的实例,它的调用顺序对应声明顺序,也就是说,如果它实现了ServletRequestListener,ServletContextListener或HttpSessionListener,那么这个新的 listener 将被添加到那个接口的 listeners 的有序列表末尾。

4.4.3.3  void addListener(Class <? extends EventListener> listenerClass)

添加指定类型的 listener 到ServletContext。给定的 listener 必须实现一个或者多个下面的接口:


■ javax.servlet.ServletContextAttributeListener

■ javax.servlet.ServletRequestListener


■ javax.servlet.ServletRequestAttributeListener

■ javax.servlet.http.HttpSessionListener 


■ javax.servlet.http.HttpSessionAttributeListener

■ javax.servlet.http.HttpSessionIdListener 


如果 ServletContext 传递给 ServletContainerInitializer 的 onStartup 方法,那么给定的 listener 除了可以实现上面列出的接口之外,也可以实现ServletContextListener。如果给定的 listener 是一个 listener 接口的实例,它的调用顺序对应声明顺序,也就是说,如果它实现了ServletRequestListener,ServletContextListener 或 HttpSessionListener,那么这个新的 listener 将被添加到那个接口的 listeners 的有序列表末尾。


4.4.3.4  <T extends EventListener> void createListener(Class<T> clazz)

这个方法实例化一个给定的 EventListener 类。这个特定的 EventListener 类必须至少实现一个下面的接口:


■ javax.servlet.ServletContextAttributeListener

■ javax.servlet.ServletRequestListener


■ javax.servlet.ServletRequestAttributeListener

■ javax.servlet.http.HttpSessionListener

■ javax.servlet.http.HttpSessionAttributeListener

■ javax.servlet.http.HttpSessionIdListener

         这个方法必须支持本规范中定义的可用于在上述 listener 接口上的所有注解。返回的 EventListener 实例在调用 addListener(T t) 注册到 ServletContext 之前可以做进一步的定制。给定的 EventListener 必须定义一个无参构造器用来实例化。


4.4.3.5  Annotation processing requirements for programmatically added Servlets, Filters and Listeners 编程化添加 Servlets, Filters 和 Listeners 的注解处理要求

除了 addServlet 使用一个实例添加或创建 servlet 之外,当使用编程API添加或创建一个Servlet时,下面的注解必须在类内被内省(?),并且定义在其中(注解)的元数据必须被使用,除非通过调用 ServletRegistration.Dynamic/ServletRegistration 中的 API 来覆盖。

@ServletSecurity, @RunAs, @DeclareRoles, @MultipartConfig.

没有注解的 Filters 和 Listeners需要被内省。

除了那些使用一个实例的方法(注:也就是通过addServlet(instance),addFileter(instance),addListener(instance))添加之外,被编程式添加或创建的所有组件(Servlets, Filters and Listeners) 上的资源注入,只有当组件是一个 CDI 托管 Bean 时才被支持。

 

4.5     Context Attributes 上下文属性

一个servlet可以通过名称绑定一个对象属性到上下文。任何绑定到上下文的属性对作为同一Web应用中一部分的其他 servlet 都是可用的。ServletContext 接口的下列方法允许来访问这个功能:

■ setAttribute


■ getAttribute


■ getAttributeNames

■ removeAttribute

4.5.1 Context Attributes in a Distributed Container  分布式容器中的上下文属性

上下文属性在其被创建的JVM中是本地的。这样防止在分布式容器中 ServletContext 中的属性被作为分享的内存存储。当需要在分布式环境中的servlets之间分享信息时,信息应该被放置到 session 中,存储到数据库或者设置在企业 JavaBeans 组件中。

 

4.6     Resources  资源

ServletContext接口只能直接访问作为Web应用一部分的静态内容文档(包括HTML,GIF和JPEG文件)的结构层级,通过 ServletContext 接口以下方法:

■ getResource


■ getResourceAsStream

getResource 和 getResourceAsStream 方法使用一个以”/“为前导的字符串作为参数,它给出了上下文根 或 相对于web 应用的 WEB-INF/lib 目录下的JAR文件的 META-INF/resources 目录的相对资源路径。这些方法在查询 WEB-INF/lib 目录下的任何 JAR 文件之前,首先搜索Web应用上下文的根。没有定义扫描 WEB-INF/lib 目录中JAR文件的顺序。这些文档结构层级可以存在于服务器的文件系统,Web应用的归档文件中,一个远端服务器或者其他什么位置。

这些方法不用于获取动态内容。例如,在一个支持JSP规范1的容器中,一个来自 getResource(“/index.jsp”) 的方法调用将返回JSP的源代码而不是处理后的输出。查看第九章,“分派请求”获取关于访问动态内容的更多信息。

使用 getResourcePaths(String path) 方法可以访问 Web 应用中资源的完整列表。这个方法语义的全部细节可以在本规范中的API文档中找到。

 

4.7      Multiple Hosts and Servlet Contexts  多主机和 Servlet 上下文

Web服务器可以支持多个逻辑主机共享一个服务器的IP地址。这种能力有时候被称为“虚拟主机”。在这种情况下,每个逻辑主机必须有自己的Servlet上下文或servlet 上下文集。Servlet 上下文不能跨虚拟主机共享。ServletContext 接口的 getVirtualServerName 方法允许访问其被部署的逻辑主机的配置名称。Servlet 容器可以支持多个逻辑主机。在一台逻辑主机上部署的所有 servlet 的上下文该方法必须返回相同的名称,该方法返回的名称必须是明确的,每个逻辑主机稳定的,并且适合用来关联服务器配置信息和逻辑主机。

4.8     Reloading Considerations 重新加载需要考虑的因素

尽管容器提供者不必为了便于开发而实现类的重新加载方案,但是任何这样的实现必须确保所有的 servlets 以及它们使用的类,在一个单独的类加载器范围内中被加载。这个要求是保证应用的行为与开发者期望一致所需要的。作为一个开发辅助,为了用在类重新加载时对Session终结的监控,容器应该支持 session 绑定 listeners 的通知的全部语法。

前几代容器创建新的类加载器加载servlet,而 servlet 上下文中加载其他 servlets 或类使用不同的类加载器。这样可能会导致在一个servlet 上下文中的对象引用指向非预期的类或者对象,并且导致无法预料的的后果。为了防止因请求新的类加载器的创建导致的问题该要求是必须的。


4.8.1 Temporary Working Directories  临时工作目录

每个Servlet 上下文需要一个临时存储目录。Servlet 容器必须为每个Servlet 上下文提供一个私有的临时目录,并且可以通过 context.tempdir 上下文属性可以访问。与这个属性相关联的对象必须是 java.io.File 类型。

在很多 servlet 引擎的实现中都提供了这样便利。当 Servlet 容器重启时,容器不必维护临时目录的内容,但是必须确保一个Servlet 上下文的临时目录的内容与运行在这个 servlet 容器中的其他 Web 应用的 servlet 上下文是不可见的。

原文地址:https://www.cnblogs.com/whilliy/p/5685250.html