上下文和依赖关系注入以及 JSF 2.0 入门指南

编写人:Andy Gibson,维护人:Troy Giunipero

此页上的内容适用于 NetBeans IDE 7.1、7.2 和 7.3

JSR-299 指定的上下文和依赖关系注入 (CDI) 是 Java EE 6 的一个组成部分,提供了一个体系结构,以允许 Java EE 组件(例如 Servlet、企业 Bean 和 JavaBeans)在具有明确定义范围的应用程序生命周期内存在。此外,CDI 服务允许 Java EE 组件(例如 EJB 会话 Bean 和 JavaServer Faces (JSF) 受管 Bean)注入并通过触发和观察事件以松散耦合的方式进行交互。

本教程基于 Andy Gibson 发布的博客,标题为:JSF 2.0 和 JEE 6 中的 CDI 入门。本教程演示如何使用 IDE 设置支持 JSF 2.0 和 CDI 的 Java Web 项目。本教程还继续演示如何连接 CDI 受管 Bean 和 Facelets 页,并在末尾提供了 CDI 与 EJB 技术集成的简短示例。

NetBeans IDE 为上下文和依赖关系注入提供了内置支持,包括在项目创建时构建 beans.xml CDI 配置文件的选项,为标注提供的编辑器和导航支持,以及用于创建常用 CDI 工件的各种向导。


要学完本教程,您需要具备以下软件和资源。

软件或资源 要求的版本
NetBeans IDE 7.1、7.2、7.3、Java EE 包
Java 开发工具包 (JDK) 版本 6
GlassFish Server Open Source Edition 3.x

注:

  • NetBeans IDE Java 包中还含 GlassFish Server Open Source Edition 3.x,后者是与 Java EE 6 兼容的容器。
  • NetBeans 6.8 Patch 1 也提供对 CDI 的支持。

创建支持 CDI 的 Java Web 项目

在本示例中,将创建一个启用了 JSF 2.0 且支持 CDI 的 Java Web 项目。

  1. 在 IDE 的主工具栏中单击 "New Project"(新建项目)() 按钮(Ctrl-Shift-N 组合键;在 Mac 上为 ⌘-Shift-N 组合键)。
  2. 在新建项目向导,选择 "Java Web" 类别,然后选择 "Web Application"(Web 应用程序)。单击 "Next"(下一步)。
  3. 键入 cdiDemo 作为项目名称,并设置项目位置。单击 "Next"(下一步)。
  4. 将服务器设置为 "GlassFish 3.x",并将 Java EE 版本设置为 "Java EE 6 Web"。确认 "Enable Contexts and Dependency Injection"(启用上下文和依赖关系注入)选项处于选中状态。
    启用新建 Web 应用程序向导中提供的 CDI 选项
    如果选中 "Enable Contexts and Dependency Injection"(启用上下文和依赖关系注入)选项,则创建项目模板时,会在项目的 WEB-INF 文件夹中生成 beans.xml 文件。CDI 使用此 beans.xml 文件指示 Java EE 兼容的服务器,此项目是包含 CDI Bean 的模块。
  5. 单击 "Next"(下一步)。
  6. 在 "Frameworks"(框架)面板中,选择 "JavaServer Faces" 选项。
  7. 单击 "Configuration"(配置)标签,并确认将 Facelets 选作 "Preferred Page Language"(首选页面语言)。单击 "Finish"(完成)。

    单击 "Finish"(完成),此时 IDE 生成 Web 应用程序项目并在编辑器中打开 index.xhtml 欢迎页。

  8. 在 "Projects"(项目)窗口中,展开 "Web Pages"(Web 页)> "WEB-INF" 文件夹节点,即会显示 beans.xml 文件。此文件当前为空,但可用于将 Bean 相关的 XML 信息指定为标注的备用选项。
    显示在

    如果展开 "Libraries"(库)> "GlassFish Server" 节点,则可以看到自动添加了 weld-osgi-bundle.jar 库。GlassFish Server 包含 Weld,这是 JBoss 的 JSR-299 CDI 规范的实现。

从 JSF 的表达式语言访问 Bean

本练习演示如何使用 EL 语法将 CDI 受管 Bean 连接到 Facelets 页。

  1. 在 "Projects"(项目)窗口中,右键单击 "Source Packages"(源包)节点并选择 "New"(新建)> "Java Class"(Java 类)。
  2. 在新建 Java 类向导中,将类命名为 MessageServerBean,并键入 exercise1 作为包。(新包在完成向导时创建。)
    新建 Java 类向导
  3. 单击 "Finish"(完成)。新类和包生成,并在编辑器中打开此类。
  4. 使用 javax.inject.Named 标注对此类进行标注,并创建单个方法以返回字符串。
    package exercise1;
    
    import javax.inject.Named;
    
    @Named
    public class MessageServerBean {
    
        public String getMessage() {
            return "Hello World!";
        }
    }
    键入 @Named 标注时,按 Ctrl-空格键可调用编辑器的代码完成支持,以及 Javadoc 文档。如果使用编辑器的代码完成功能应用标注(例如,选择相应的标注,然后按 Enter),import 语句将自动添加到文件中。

    在 Javadoc 弹出式窗口中,也可以单击 "Show documentation in external web browser"(在外部 Web 浏览器中显示文档)() 按钮以在单独的窗口中显示 Javadoc 全图。
  5. 保存文件(Ctrl-S;在 Mac 上为 ⌘-S)。根据 CDI 的定义,通过添加 @Named 标注,MessageServerBean 类成为受管 Bean
  6. 在编辑器中切换至 index.xhtml Facelets 页(按 Ctrl-Tab 组合键),然后在 <h:body> 标记中添加以下内容。
    <h:body>
        Hello from Facelets
        <br/>
        Message is: #{messageServerBean.message}
        <br/>
        Message Server Bean is: #{messageServerBean}
    </h:body>
    可以在 EL 表达式中按 Ctrl-空格键以使用代码完成建议。编辑器的代码完成列出了受管 Bean 及其属性。因为 @Named 标注将 MessageServerBean 类转换成 CDI 受管 Bean,该 CDI 受管 Bean 与作为 JSF 受管 Bean 时一样,可以在 EL 语法中访问。
    新建 Java 类向导
  7. 在 IDE 的主工具栏中单击 "Run Project"(运行项目)() 按钮。编译该项目并将其部署到 GlassFish,并在浏览器中打开应用程序欢迎页 (index.xhtml)。您将看到来自该页上显示的 MessageServerBean 的 "Hello World!" 消息。
    显示在浏览器中的欢迎页
  8. 返回至消息 Bean 并将消息更改为其他内容(例如,"Hello Weld!")。保存文件(Ctrl-S 组合键;在 Mac 上为 ⌘-S 组合键),然后刷新浏览器。将自动显示新消息。因为有了 IDE 的“在保存时部署”功能,保存的任何更改都会自动进行编辑并重新部署到服务器。

    从此页第三行,您可以看到类名为 exercise1.MessageServerBean。请注意,Bean 只是一个 POJO(Plain Old Java Object,简单传统 Java 对象)。即使您现在使用 Java EE 进行开发,事务、拦截器以及重复出现的所有“重型”功能等层中也不会包含复杂的类分层结构。

这是怎么回事?

当部署应用程序时,beans.xml 文件存在即表明该模块包含 CDI 受管 Bean,因此将扫描该路径下的类的 CDI 标注。在 CDI 模块中,所有 Bean 会在 Weld 中注册,并使用 @Named 标注将 Bean 与注入点匹配。当呈现 index.xhtml 页时,JSF 会尝试使用 JSF 中注册的表达式解析器来解析本页中的 messageServerBean 值。其中一个解析器是 Weld EL 解析器,它以名称 messageServerBean 注册了 MessageServerBean 类。本可以使用 @Named 标注指定一个不同的名称,但是我们并没有这样做,因此它是以默认名称注册的,且类名的首字母为小写。Weld 解析器返回此 Bean 的实例以响应来自 JSF 的请求。Bean 命名仅在使用 EL 表达式时需要,且不应作为注入机制使用,因为 CDI 提供了按类类型和限定符标注的类型安全的注入。


升级到 EJB

由于有 EJB 3.1,即使现在使用的是 Java EE 堆栈,也只需进行小幅改动,即可轻松将 Bean 部署为 EJB。

  1. 打开 MessageServerBean,并在类级别添加 javax.ejb.Stateless 标注,然后将字符串更改为 "Hello EJB!"。
    package exercise1;
    
    import javax.ejb.Stateless;
    import javax.inject.Named;
    
    /**
     *
     * @author nbuser
     */
    @Named
    @Stateless
    public class MessageServerBean {
    
        public String getMessage() {
            return "Hello EJB!";
        }
    }
  2. 保存文件(Ctrl-S 组合键;在 Mac 上为 ⌘-S 组合键),然后转到浏览器并刷新。将看到类似于以下内容的输出:
    显示在浏览器中的 EJB 详细信息
    太奇妙了,只需一个标注即可将 POJO 转换为功能完善的 EJB。保存更改并刷新页面以后,即可显示更改。通过执行此操作,不需要创建任何古怪的项目配置、本地接口或深奥的部署描述符。

不同的 EJB 类型

还可以尝试使用 @Stateful 标注。或者,您可以尝试对 singleton 实例使用新的 @Singleton 标注。如果执行此操作,会注意到其中存在两个标注:javax.ejb.Singletonjavax.inject.Singleton。为什么存在两个 singletons 标注?如果是在非 EJB 环境中使用 CDI,通过 CDI singleton (javax.inject.Singleton) 可以在 EJB 外定义 singleton 实例。EJB singleton (javax.ejb.Singleton) 提供了 EJB 的所有功能,例如事务管理。因此,您可以根据需要以及是否使用的是 EJB 环境来进行选择。


另请参见

本系列的下一部分重点介绍 CDI 注入,并详细讲解在 Java EE 6 环境中使用 CDI 管理依赖关系。

有关 CDI 和 JSF 2.0 的详细信息,请参见以下资源。

get support for the NetBeans

Support


By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2013, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo