将 JAX-RS 2.0 与 EJB 和 CDI 集成
在 WebSphere® Application Server(传统) V9 中,Java™ API for RESTful Web Services (JAX-RS) 2.0 与 Enterprise JavaBeans (EJB) 和上下文和依赖关系注入 (CDI) 集成。
为使 JAX-RS 2.0 使用企业 Bean,您需要使用 @Path 对 bean 的类进行注释并将其转换为根资源类。
通过与 EJB 集成,可对 EJB bean 进行注释以将其显示为 REST 端点。还可以使用 Java Transaction API (JTA) 和 EJB 的安全功能。WebSphere Application Server(传统) 中的 JAX-RS 2.0 支持将无状态和单独会话 bean 用作根资源类、提供程序和应用程序子类。
通过与 CDI 集成,您可将 CDI bean 或受管 bean 作为 REST 端点注释并对 Web Service 使用 CDI 注入。WebSphere Application Server(传统) 中的 JAX-RS 2.0 支持将 CDI 样式的 bean 用作根资源类、提供程序和应用程序子类。提供程序和应用程序子类必须是单体或使用应用程序范围。CDI 规范简化了集成不同类型的 Java EE 组件的过程。它提供了一种常用机制,用于将 EJB 组件或受管 Bean 之类的组件插入到 Java Server Pages (JSP) 或其他 EJB 之类的其他组件中。
- 对于无状态会话 bean,请按以下示例中所示使用 @Stateless 注释:
@Stateless @Path("stateless-bean") public class StatelessResource {...}
- 对于单体 bean,请按以下示例中所示使用 @Singleton 注释:
@Singleton @Path("singleton-bean") public class SingletonResource {...}
@ApplicationScoped
@Path("/ApplicationScopedResource")
public class ApplicationScopedResource {
private @Inject
SimpleBean injected;
...
}
对 JAX-RS 2.0 与 EJB 和 CDI 的限制
请参阅以下有关 WebSphere Application Server(传统) 中 JAX-RS 2.0 的限制的项:
- 如果使用 EJB 作为 JAX-RS 资源、提供程序或应用程序,那么不能对 EJB bean 的构造函数使用 @Context 注入。注: 此情况的原因是具有缺省构造函数的 EJB 仅可用于基于 EJB 的 JAX-RS 和 JAX-RS 规范。
- 针对应用程序类,如果未实现接口或具有 @Localbean 注释,那么会将其视作 EJB。但是如果此类未实现本地或 POJO 接口,那么不会将其视为 EJB。
- 针对提供程序,此处列出是否可将类视为有效 EJB 提供程序的条件:
- 如果类仅实现不带 @Local 注释的 POJO 提供程序接口,那么会将其视为有效 EJB 提供程序。
- 如果类具有 @LocalBean 注释且实现 POJO 提供程序接口,那么会将其视为有效 EJB 提供程序。
- 如果类有带 @Local 注释的本地接口,那么本地接口是提供程序接口。如果此类实现提供程序接口,那么它是有效 EJB 提供程序。
- 如果类有带 @Local 注释的本地接口,且本地接口不是提供程序接口,那么它不是有效提供程序。此情况的原因是,EJB 容器仅可生成本地接口而不是 POJO 提供程序接口的 EJB 存根。
- 如果类有 @Local 注释,但此注释不实现其引用的提供程序接口,那么它不是有效提供程序。根据 JAX-RS 2.0 规范,提供程序是实现一个或多个 JAX-RS 接口的类,这些接口在此规范中进行了介绍且可能具有用于自动发现的 @Provider 注释。
- 针对资源,此处列出是否将类中方法作为 JAX-RS 资源提供的条件:
- 如果基于 EJB 的资源未实现任何接口,那么此类中声明的所有方法可作为 JAX-RS 资源提供。
- 如果基于 EJB 的资源实现一个接口(本地或 POJO),那么此接口中声明的所有方法将作为 JAX-RS 资源提供。
- 如果基于 EJB 的资源实现多个接口,那么:
- 如果所有接口为不带 @Local 注释的 POJO 接口,那么接口中声明的所有方法将作为 JAX-RS 资源提供。
- 如果所有接口为带 @Local 注释的 POJO 接口,那么接口中声明的所有方法将作为 JAX-RS 资源提供。
- 如果某些接口是带 @Local 注释的本地接口而其他接口不是本地接口,那么仅本地接口中声明的方法会作为 JAX-RS 资源提供。注: 此情况的原因是,在此场景中,EJB 容器仅可生成本地接口的 EJB 存根。
- 如果基于 EJB 的资源具有 @LocalBean 注释,那么类中声明的所有方法将作为 JAX-RS 资源提供。
- 如果基于 EJB 的资源实现接口,那么必须在此接口中声明 JAX-RS 资源方法。如果接口是无法修改的提供程序,那么必须创建资源类的新接口以添加资源方法。否则,它不会被视为 EJB 资源。
- 如果带 @Path 注释的资源类实现 JAX-RS 提供程序接口或它使用 @Provider 注释进行声明,那么此类同时用作资源和提供程序。在此情况下,JAX-RS 2.0 引擎仅使用此类的一个实例(由资源和提供程序共享),此实例的生命周期为单体,这是缺省情况。
- 如果同时在应用程序类的 getClasses 和 getSingletons 方法中注册类,那么缺省情况下,JAX-RS 2.0 引擎会使用来自 getSingletons 方法的实例,并忽略 getClasses 方法中的注册。
- 如果 RESTful 资源也是 CDI 管理的 bean 并且其范围为 javax.enterprise.context.Dependent,那么会因为 CDI 限制而不能调用 PreDestroy 方法。
JAX-RS 2.0 bean 生命周期和 EJB bean 生命周期
Application | JAX-RS 2.0 | EJB | 结果 |
---|---|---|---|
资源 | perRequest | 无状态 | 无状态 |
perRequest | 独立 | 独立 | |
独立 | 无状态 | 无状态 | |
独立 | 独立 | 独立 | |
提供程序 | 独立 | 无状态 | 无状态 |
独立 | 独立 | 独立 |
JAX-RS 2.0 范围生命周期和 CDI 范围生命周期
Application | JAX-RS 2.0 范围 | CDI 范围注释 | 结果 |
---|---|---|---|
资源 | perRequest | @ApplicationScoped | 独立 |
perRequest | @RequestScoped | perRequest | |
perRequest | @Dependent | perRequest | |
perRequest | @SessionScoped | 会话 | |
perRequest | perRequest | ||
独立 | @ApplicationScoped | 独立 | |
独立 | @RequestScoped | perRequest | |
独立 | @Dependent | 独立 | |
独立 | @SessionScoped | Session | |
独立 | 独立 | ||
提供程序 | 独立 | @ApplicationScoped | 独立 |
独立 | @RequestScoped | 独立 | |
独立 | @Dependent | 独立 | |
独立 | @SessionScoped | 独立 | |
独立 | 独立 |
JAX-RS 2.0 范围生命周期和 CDI 范围生命周期冲突消息
如果 JAX-RS 2.0 与 CDI 两者的范围生命周期冲突,那么会显示以下警告消息。它们只是警告消息,不需要执行任何操作。
如果 JAXRS-2.0 资源范围与 CDI 范围不匹配,且 CDI 中存在资源实例,那么会显示此消息,以便 WebSphere Application Server(传统) 可从 CDI 获取资源实例。如果实例来自 JAX-RS,那么它未包含 CDI 注入。CWWKW1001W: JAXRS-2.0 资源 {0} 的范围 {1} 与 CDI 范围 {2} 不匹配。WebSphere Application Server 传统版从 {3} 获取资源实例。
显示此消息的原因是该提供程序实例仅为“单体”。如果提供程序的 CDI 范围是 Dependent 或 ApplicationScoped,那么 WebSphere Application Server(传统) 会从此 CDI 获取提供程序实例。如果实例来自 JAX-RS,那么它未包含 CDI 注入。CWWKW1002W: JAXRS-2.0 提供程序 {0} 的 CDI 范围为 {1}。WebSphere Application Server 传统版从 {2} 获取提供程序实例。