20200311 15.与其它规范有关的要求
15.与其它规范有关的要求
本章列出对 web 容器的要求,它已经包含在容器产品中了,还包括其他 Java 技术。
下面章节中任何涉及到 Java EE 应用的 profile,不只是完整的 Java EE profile,还包括任何支持 Servelt 的 profile,像 Java EE Web Profile。有关配置文件的更多信息,请参阅 Java EE 平台规范。
15.1 会话
属于 Java EE 实现的分布式 servlet 容器必须支持其他 Java EE 对象从一个 JVM 迁移到另一个 JVM 所必需的机制。
15.2 Web 应用程序
15.2.1 Web 应用程序类加载器
Servlet 容器是一个 Java EE 产品的一部分,不应该允许应用程序重写 Java SE 或 Java EE 平台的类,比如那些在 java.
和 javax.*
命名空间中的类, Java SE 或 Java EE 不允许被修改。
15.2.2 Web 应用程序环境
Java EE 定义了一个命名的环境,允许应用程序在没有明确的知道外部信息是如何命名和组织的情况下轻松地访问资源和外部信息。
由于 servlet 是 Java EE 技术的一个完整的组件类型,已经在 Web 应用程序部署文件中规定了允许 servlet 获取引用资源和企业 bean 的指定信息。此包含信息的的部署元素有:
env-entry
ejb-ref
ejb-local-ref
resource-ref
resource-env-ref
service-ref
message-destination-ref
persistence-context-ref
persistence-unit-ref
开发人员使用这些元素来描述在 Web 容器中运行时 Web 应用程序需要在 JNDI 命名空间中注册的某些对象。
Java EE 规范第 5 章中描述了关于 Java EE 环境设置的要求。
Servlet 容器属于 Java EE 技术标准实现的一部分,它必须支持这种语法。查阅 Java EE 规范可获取更多详细信息。这种类型的 servlet 容器必须支持查找这种对象并在受 servlet 容器管理的线程上执行时调用这些对象。
当在开发人员创建的线程上执行时,这种类型的 servlet 容器应该支持这种行为,但目前没有要求这样做。
这样的规定将被添加到本规范的下一个版本中。开发人员应该小心,不推荐应用程序创建的线程依赖这种能力,因为它是不可移植的。
15.2.3 Web 模块上下文根 URL 的 JNDI 名称
Java EE 平台规范定义了一个标准化的全局 JNDI 命名空间和一系列相关的命名空间映射到不同的 Java EE 应用程序范围。应用程序可以使用这些命名空间可移植地检索组件和资源的引用。本节定义的 Web 应用程序的基本 URL 是需要注册的 JNDI 名称。
为一个 Web 应用程序上下文根目录预定义的 java.net.URL
资源的名称的语法如下:
全 局 命 名 空 间 中 java:global[/<app-name>]/<module-name>!ROOT
, 应 用 程 序 指 定 的 命 名 空 间 中 java:app/<module-name>!ROOT
。
确定应用程序名称和模块名称的规则请参阅 Java EE 规范 8.1.1 节(组件创建)和 8.1.2 节(应用程序组装)。
只有当 Web 应用打包成一个.ear
文件时才适合使用<app-name>
。
java:app
前缀允许一个组件内执行的 Java EE 应用程序来访问特定于应用程序的命名空间。 java:app
名称允许一个企业应用程序中的模块引用同一个企业应用程序中其他模块的上下文根目录。 <module-name>
是 java:app
url 语法的必要组成部分。
然后,可以在应用程序使用上述的 URL,如下:
如果 Web 应用程序使用模块名称 myWebApp
独立部署。 URL 可被注入到另一个 web 模块,如下:
代码示例 15-1
@Resource(lookup="java:global/myWebApp!ROOT")
URL myWebApp;
当打包到一个名为 myApp
的 EAR 文件中时,可像下面这样使用:
代码示例 15-2
@Resource(lookup="java:global/myApp/myWebApp!ROOT")
URL myWebApp;
15.3 安全性
本节详细介绍了 Web 容器包含在一个产品中时额外的安全性要求,还包含 EJB
、 JACC
和(或) JASPIC
。
以下各节将介绍这些要求。
15.3.1 EJB™调用传播的安全标识
必须始终提供一个安全标识或主体(principal),用于调用一个企业 bean。从 Web 应用程序中调用企业 Bean 的默认模式是为把 Web 用户的安全标识传播到 EJB 容器。
在其他情况下, Web 容器必须允许不了解 Web 容器或 EJB 容器的 web 用户进行调用:
- Web 容器必须支持未把自己授权给容器的用户访问 Web 资源。 这是在互联网上访问 Web 资源常见的模式。
- 应用程序代码可以是单点登录和基于调用者标识的定制化数据的唯一处理器。
在这些情况下, Web 应用程序部署描述文件可以指定一个 run-as
元素。当为 Servlet 指定了一个 run-as
角色时, Servlet 容器必须传播主要的映射到该角色,作为任何从 Servlet 到 EJB 调用的安全标识,包括从 Servlet 的 init
和 destory
方法进行原始调用。安全角色名必须是为 Web 应用程序定义的安全角色名称之一。
由于 Web 容器作为 Java EE 平台的一部分运行,在同一个 Java EE 应用程序中调用 EJB 组件,以及调用部署在其他 Java EE 中的应用程序都必须支持 run-as
元素的使用。
15.3.2 容器授权的要求
在 Java EE 产品中或包括支持 Java 容器授权合约( JAAC, i.e, JSR 115)的产品中,所有 Servlet 容器必须实现支持 JACC。
JACC 规范可在此处下载
15.3.3 容器认证的要求
在 Java EE 产品中或包括支持 Java 容器认证 SPI( JASPIC, i.e, JSR 196)的产品中,所有 Servlet 容器必须实现 JASPIC 规范的 Servlet 容器 Profile。
JASPIC 规范可在此处下载
15.4 部署
本节将详述一个符合 JavaEE 技术的容器和包含支持 JSP 和/或 Web Service 的产品的部署描述符、打包和部署描述符处理的要求。
15.4.1 部署描述符元素
以下附加元素存在于 Web 应用程序部署描述符,用于满足 Web 容器开启 JSP 页面的要求,或作为 JavaEE 应用服务器的一部分。它们不需要由希望仅支持 Servlet 规范的容器支持:
jsp-config
- 用于描述资源引用的语法 (
env-entry
,ejb-ref
,ejb-local-ref
,resource-ref
,resource-env-ref
) - 指定消息目的地的语法 (
message-destination
,message-destination-ref
) - 引用 Web Service (
service-ref
) - 引用持久化上下文(
persistence-context-ref
) - 引用持久化单元 (
persistence-unit-ref
)
这些元素的语法现在由 Java 服务器页面( JavaServer Pages)规范 2.2 版本,和 Java EE 规范控制。
15.4.2 打包和 JAX-WS 组件部署
Web 容器可以选择支持运行实现 JAX-RPC 和/或 JAX-WS 规范定义的 Web 服务端点( endpoint)编写的组件。需要 Web 容器嵌入一个 Java EE 符合的实现来支持 JAX-RPC 和 JAX-WS Web Service 组件。本节描述了 Web 容器包括也支持 JAX-RPC 和 JAX-WS 的产品的打包和部署模型。
JSR-109 定义了用于打包 Web service 接口与它关联的 WSDL 描述和关联的类的模型。它定义了一种机制用于启用了 JAX-WS 和 JAX-RPC 的容器链接到一个实现了这个 Web service 的组件。一个 JAX-WS 或 JAX-RPC Web service 实现组件使用 JAX-WS 和/或 JAX-RPC 规范定义的 API,其定义了它与启用了 JAX-WS 和/或 JAX-RPC 的 Web 容器之间的契约。它被打包到 WAR 文件。 Web service 开发人员使用平常的<servlet>
声明来声明这个组件。
启用了 JAX-WS 和 JAX-RPC 的 Web 容器必须支持开发人员在使用的 Web 部署描述符中定义用于端点实现组件的如下信息,使用与 HTTP Servlet 组件使用的 Servlet 元素相同的语法。子元素用于以如下方式指定端点信息:
servlet-name
元素定义可用于找出 WAR 中的处于其他组件中的这个端点描述的逻辑名字servlet-class
元素提供这个端点实现的全限定 Java 类名description
元素可以用于描述该组件,并可能显示在一个工具中load-on-startup
元素指定 Web 容器中的组件相对于其它组件的初始化顺序security-role-ref
元素可以用于测试是否已通过身份认证的用户在一个逻辑安全角色中run-as
元素可以用于覆盖该组件到 EJB 调用的身份传播
由开发人员定义的用于这个组件的任何 Servlet 初始化参数可能被容器忽略。此外,启用了 JAX-WS 和JAX-RPC 的 Web 组件继承了用于定义如下信息的传统 Web 组件机制:
- 使用 Servlet 映射技术映射组件到 Web 容器的 URL 命名空间
- 使用安全约束在 Web 组件上授权约束
- 能够使用 servlet 过滤器提供底层( low-level)字节流支持,用于使用过滤器映射技术操纵 JAX-WS 和/或 JAX-RPC 消息
- 任何与组件关联的 HTTP 会话的超时特性
- 链接到存储在 JNDO 命名空间的 Java EE 对象
所有上述要求可使用定义在 8-69 页 8.2 节的“可插拔性”的插拔机制得到满足。
15.4.3 处理部署描述符的规则
符合 Java EE 技术实现一部分的容器和工具,需要根据 XML schema 验证部署描述符结构的正确性。建议验证,但对于不符合 Java EE 技术实现的 web 容器和工具不是必须的。
15.5 注解和资源注入
Java 元数据( Metadata)规范( JSR-175),是 J2SE 和更高版本的一部分,提供一种在 Java 代码中指定配置数据的方法。 Java 代码中的元数据也被称为注解。在 JavaEE 中,注解用于声明对外部资源的依赖和在 Java 代码中的配置数据而无需在配置文件中定义该数据。
本节描述了在 Java EE 技术兼容的 Servlet 容器中注解和资源注入的行为。本节扩展了 Java EE 规范第 5 节标题为“资源,命名和注入”。
注解必须支持以下容器管理的类,其实现了以下接口并声在 web 应用部署描述符中明,或使用定义在 8-65 页 8.1 节“注解和可插拔性”的注解声明或编程式添加的。
表 15-1 支持注解和依赖注入的组件和接口
组件类型 | 实现以下接口的类 |
---|---|
Servlet | javax.servlet.Servlet |
Filter | javax.servlet.Filter |
Listener | javax.servlet.ServletContextListener javax.servlet.ServletContextAttributeListener javax.servlet.ServletRequestListener javax.servlet.ServletRequestAttributeListener javax.servlet.http.HttpSessionListener javax.servlet.http.HttpSessionAttributeListener javax.servlet.http.HttpSessionIdListener javax.servlet.AsyncListener |
Web 容器不需要为存在注解的除了上表 15-1 列出的那些类执行资源注入。
引用必须在任何生命周期方法调用之前注入,且组件实例对应用是可用的。
在一个 web 应用中,使用资源注入的类只有当它们位于 WEB-INF/classes
目录,或如果它们被打包到位于 WEB-INF 目录下的 jar 文件中,它们的注解将被处理。容器可以选择性地为在其他地方的应用类路径中找到的类处理资源注入注解。
Web 应用部署描述符的 web-app 元素上包含一个 metadata-complete
属性。 metadata-complete
属性定义了 web.xml
描述符是否是完整的,或是否应考虑部署过程中使用的其他资源的元数据。元数据可能来自 web.xml
文件、 web-fragment.xml
文件、 WEB-INF/classes
中的类文件上的注解、和 WEB-INF/lib
目录中的 jar 文件中的文件上的注解。如果 metadata-complete
设置为“ true
”,部署工具仅检查 web.xml
文件且必须忽略如出现在应用的类文件上的@WebServlet
、 @WebFilter
、和@WebListener
注解,且必须也忽略 WEB-INF/lib
中的打包在 jar 文件的任何 web-fragment.xml
描述符。如果 metadata-complete
没有指定或设置为“ false
”,部署工具必须检查类文件和 web-fragment.xml
文件的元数据,就像前面指定的那样。
web-fragment.xml
的 web-fragment
元素也包含了 metadata-complete
属性。该属性定义了对于给定片段的 web-fragment.xml
描述符是否是完整的,或者是否应该扫描相关的 jar 文件中的类中的注解。如果 metadata-complete
设置为“ true
”,部署工具仅检查 web-fragment.xml
文件且必须忽略如出现在 fragment 的类文件上的@WebServlet
、 @WebFilter
、和@WebListener
注解。如果 metadata-complete
没有指定或设置为 “ false
”,部署工具必须检查类文件的元数据。
以下是 Java EE 技术兼容的 web 容器需要的注解。
15.5.1 @DeclareRoles
该注解用于定义由应用安全模型组成的安全角色。该注解指定在类上,且它用于定义能从注解的类的方法内测试(即,通过调用 isUserInRole
)的角色。由于用在@RolesAllowed
而隐式声明的角色,不必使用 @DeclareRoles
注解明确声明。 @DeclareRoles
注解仅可以定义在实现了javax.servlet.Servlet
接口或它的一个子类的类中。
以下是如果使用该注解的一个例子。
代码示例 15-3 @DeclareRoles
注解示例
@DeclareRoles("BusinessAdmin")
public class CalculatorServlet {
//...
}
声明@DeclareRoles ("BusinessAdmin")
等价于如下在 web.xml
中的定义。
代码示例 15-4 @DeclareRoles
web.xml
<web-app>
<security-role>
<role-name>BusinessAdmin</role-name>
</security-role>
</web-app>
该注解不是用于重新链接( relink)应用角色到其他角色。当这样的链接是必需的,它是通过在相关的部署描述符中定义一个适当的 security-role-ref
来实现。
当从注解的类调用 isUserInRole
时,与调用的类关联的调用者身份以相同名称作为 isCallerInRole
的参数来测试角色成员身份。如果已经定义了参数 role-name
的一个 security-role-ref
,调用者测试映射到 role-name
的角色成员身份。
为进一步了解@DeclareRoles
注解细节,请参考 Java™平台™的通用注解(Common Annotation)规范(JSR250)第 2.10 节。
15.5.2 @EJB 注解
企业级 JavaBean™ 3.2 (EJB)组件可以从一个 web 组件使用@EJB
注解引用。
@EJB
注解提供了与部署描述符中声明 ejb-ref
或 ejb-local-ref
元素等价的功能。有一个相应的@EJB
注解的字段被注入一个相应的 EJB 组件的引用。
一个例子:
@EJB
private ShoppingCart myCart;
在上述情况下,到 EJB 组件“ myCart”的一个引用被注入作为私有字段“myCart”的值,在声明注入的类可用之前。
进一步了解@EJB
注解的行为请参考 EJB 3.0 规范( JSR 220)第 15.5 节。
15.5.3 @EJBs 注解
@EJBs
注解允许在单个资源上声明多于一个@EJB
注解。
一个例子:
代码示例 15-5 @EJBs
注解示例
@EJBs({@EJB(Calculator), @EJB(ShoppingCart)})
public class ShoppingCartServlet {
//...
}
上面例子中的 EJB 组件 ShoppingCart
和 Calculator
对 ShoppingCartServlet
是可用的。ShoppingCartServlet
仍然必须使用 JNDI 查找引用,但不需要声明在 web.xml
文件中。
@EJBs
注解讨论的进一步细节请参考 EJB 3.0 规范( JSR 220)第 15.5 节。
15.5.4 @Resource 注解
@Resource
注解用于声明到资源的引用,如一个数据源( data source)、 Java 消息服务( JMS)目的地、或环境项( environment entry)。该注解等价于在部署描述符中声明 resource-ref
、 message-destination-ref
、或 env-ref
、或 resource-env-ref
元素。
@Resource
注解指定在一个类、方法或字段上。容器负责注入到由@Resource
注解声明的资源的引用和映射到适当的 JNDI 资源。请参考 Java EE 规范第 5 章进一步了解细节。
以下是一个@Resource
注解的例子:
代码示例 15-6 @Resource
示例
@Resource
private javax.sql.DataSource catalogDS;
public getProductsByCategory() {
// get a connection and execute the query
Connection conn = catalogDS.getConnection();
..
}
在上面的示例代码中, servlet、 filter 或 listener 声明一个 javax.sql.DataSource
类型的 catalogDS
字段,在该组件对应用可用之前由容器注入数据源引用。数据源 JNDI 映射是从字段名“ catalogDS”和类型( javax.sql.DataSource
)推导出来的。此外, catalogDS 数据源不再需要定义在部署描述符中。
进一步了解@Resource
注解的语义请参考 Java™平台™的通用注解规范( JSR 250)第 2.3 节和 Java EE 规范第 5.2.5 节。
15.5.5 @PersistenceContext 注解
该注解指定容器管理的用于引用持久化单元( persistence unit)的实体管理器( entity manager)。
一个例子:
代码示例 15-7 @PersistenceContext
示例
@PersistenceContext (type=EXTENDED)
EntityManager em;
进一步了解@PersistenceContext
注解的行为请参考 Java 持久化 API( Java Persistence API) 2.1 版本第 10.5.2 节( JSR 338)。
15.5.6 @PersistenceContexts 注解
PersistenceContexts
注 解 允 许 在 一 个 资 源 上 声 明 多 于 一 个 @PersistenceContext
。 进 一 步 了 解 @PersistenceContexts
注解的行为请参考 Java 持久化 API( Java Persistence API) 2.1 版本第 10.5.2 节( JSR 338)。
15.5.7 @PersistenceUnit 注解
@PersistenceUnit
注解提供声明在 servlet 中的到企业级 JavaBean 组件实体管理器工厂( entity manager factory)的引用。实体管理器工厂绑定到一个单独的 persistence.xml
配置文件, 该文件在 EJB 3.2 规范( JSR 345)中描述。
一个示例:
代码示例 15-8 @PersistenceUnit
示例
@PersistenceUnit
EntityManagerFactory emf;
进一步了解@PersistenceUnit
注解的行为请参考 Java 持久化 API( Java Persistence API) 2.1 版本第 10.5.2 节( JSR 338)。
15.5.8 @PersistenceUnits 注解
该注解允许在一个资源上声明多于一个@PersistentUnit
。进一步了解@PersistentUnits
注解的行为请参考 Java 持久化 API( Java Persistence API) 2.1 版本第 10.5.2 节( JSR 338)。
15.5.9 @PostConstruct 注解
@PostConstruct
注解声明在一个无参的方法上,且必须不抛出任何受查异常。返回值必须是 void
。该方法必须在资源注入完成之后被调用且在组件的任何生命周期方法之前被调用。
一个例子:
代码示例 15-9 @PostConstruct
示例
@PostConstruct
public void postConstruct() {
...
}
上面的示例展示了一个使用@PostConstruct
注解的方法。
@PostConstruct
注解必须支持那些支持依赖注入的所有类并即使该类不要求任何资源注入也会被调用。如果该方法抛出未受查一次,该类必须不被放入服务中且该实例没有方法被调用。
参考 Java EE 规范第 2.5 节和 Java™平台™的通用注解规范的第 2.5 节获取更多细节。
15.5.10 @PreDestroy 注解
@PreDestroy
注解声明在容器管理组件的一个方法上。该方法在容器移除该组件之前调用。
一个例子:
代码示例 15-10 @PreDestroy
示例
使用@PreDestroy
注解的该方法必须返回 void
且必须不抛出受查异常。该方法可以是 public
、 protected
、package
私有或 private
。该方法必须不是 static
的,但它可以是 final
的。
@PreDestroy
public void cleanup() {
// clean up any open resources
...
参考 JSR 250 第 2.6 节获取更多细节。
15.5.11 @Resources 注解
由于 Java 元数据规范不允许在相同的注解目标以相同名字使用多个注解,因此@Resources
注解充当容器的多个@Resource
注解。
一个例子:
代码示例 15-11 @Resources
示例
@Resources ({
@Resource(name=”myDB” type=javax.sql.DataSource),
@Resource(name=”myMQ” type=javax.jms.ConnectionFactory)
})
public class CalculatorServlet {
//...
}
15.5.12 @RunAs 注解
@RunAs
注解等价于部署描述符中的 run-as
注解。 @RunAs
注解可能仅定义在 javax.servlet.Servlet
接口或它的子类的类实现上。
一个例子:
代码示例 15-12 @RunAs
示例
@RunAs(“Admin”)
public class CalculatorServlet {
@EJB
private ShoppingCart myCart;
public void doGet(HttpServletRequest, req, HttpServletResponse res) {
//....
myCart.getTotal();
//....
}
//....
}
@RunAs(“Admin”)
语句将等价于以下在 web.xml
中定义的。
代码示例 15-13 @RunAs
web.xml
示例
<servlet>
<servlet-name>CalculatorServlet</servlet-name>
<run-as>Admin</run-as>
</servlet>
以上示例展示了当调用 myCart.getTotal()
方法时 Servlet 如何使用@RunAs
注解来传播安全身份“ Admin”到EJB 组件。进一步了解传播身份的细节请看 15-180 页的第 15.3.1 节“ EJB™调用的安全身份传播”。
进一步了解@RunAs
注解的细节请参考 Java™平台™的通用注解规范( JSR 250)第 2.6 节。
15.5.13 @WebServiceRef 注解
@WebServiceRef
注解在一个 web 组件中使用可能在部署描述符中的 resource-ref
相同的方式提供一个到 web service 的引用。
一个例子:
@WebServiceRef
private MyService service;
在这个例子中,一个到 web service “MyService” 的引用将被注入到声明该注解的类。
进一步了解这个注解和行为,请参考 JAX-WS 规范( JSR 224)第 7 章。
15.5.14 @WebServiceRefs 注解
这个注解允许在单个资源上声明多于一个的@WebServiceRef
注解。进一步了解这个注解的行为请参考 JAX-WS 规范( JSR 224)第 7 章。
15.5.15 JavaEE 要求的上下文和依赖注入
在一个支持 JavaEE( CDI)上下文和依赖注入且 CDI 开启的产品中,实现必须支持使用 CDI managed bean。
Servlet
、 Filter
、 Listener
和 HttpUpgradeHandler
必须支持 CDI 注入和描述在 EE.5.24 节的拦截器使用, JavaEE 7 平台规范“支持依赖注入”。