适用于云环境的 JSF 2.0,第 1 部分

作者:Deepak Vohra

2012 年 4 月发布

下载:
下载Oracle JDeveloper 11.1.2
下载Oracle Database 11g 快捷版
下载示例应用程序

简介

JavaServer Faces 2.0 提供了非常适合云环境虚拟化计算资源的特性。在这个由两部分组成的文章的第一部分中,我们将探讨 @ManagedBean 批注、隐式导航和资源处理。

云计算的特征是虚拟化计算资源。如针对 Java Platform, Enterprise Edition 7 (Java EE 7) 的 JSR 342 所述,“Java EE 平台基于容器的模型及其带来的资源访问抽象使该平台已经非常适合云环境。”基于容器的模型使可移植的应用程序既能用于单机,也能用于大型集群,因此非常适合通过云架构实现扩展。

资源抽象的结果是可从任何资源位置加载资源,如类路径、文件系统、FTP 和 HTTP 位置。应用程序所需的其他资源也可同理加载。资源基本上得到了很好的管理。

开发 JavaServer Faces 2.0 (JSF 2.0) 时可能并未考虑云服务,但 JSF 2.0 却提供了非常适合云环境的特性,例如:

  • JSF 2.0 中基于路径的资源处理大大降低了虚拟化资源处理难度,并通过组合组件提供可伸缩性。
  • JSF 2.0 中 REST 式 GET 请求和可收藏的 URL 支持云架构。表示状态传输 (REST) 软件架构基于 URI 标识的资源的表示传输。REST 式资源或服务以 URI 路径方式提供。可以使用多种格式访问资源,如 XML、HTML、纯文本、PDF、JPEG 和 JSON 等。REST 的优点在于简单、轻型、快速。
  • 通过提供基于浏览器的交互式 Web 应用程序,JSF 2.0 中的 Ajax 支持可与软件即服务 (SaaS) 集成。
  • 云供应商以不同的方式提供 JSF 2.0 支持。例如,Oracle 公有云为 JSF 2.0 以及从 Oracle JDeveloper、Eclipse 和 NetBeans 部署到云提供内置支持,Oracle 公有云上的 Oracle WebLogic Server 可用于部署。基于云的 Google Application Engine (GAE) 则需要配置 JSF 2.0。
  •  

本文是由两部分组成的系列的第一部分,阐述了 JSF 2.0 中的以下新特性,正是这些特性使 JSF 2.0 适合云环境:

  • 资源处理
  • @ManagedBean 批注
  • 隐式导航
  •  

本系列的第二部分将探讨:

  • Ajax 支持
  • 视图参数
  • 预导航
  • 事件处理
  • 可收藏的 URL

资源处理

通常,资源处理的重要性源于资源加载机制。JSF 2.0 之前,组件库使用 servlet 筛选器或其他方法(如缓冲整个响应)向响应添加其他资源。JSF 2.0 引入了统一资源处理,所有组件库都遵循此机制,这增强了组件库兼容性,进而提供了一大优势。

基于路径的资源处理非常适合云环境。将 Web 应用程序资源上载到云上的一个目录结构,然后通过基于路径的资源处理获取这些资源,而不是使用 getClass().getResourceAsStream() 从类路径中读取它们 — 这简化了云环境的资源处理。

Web 应用程序运行时通常需要资源、关联文件,如 JavaScript、级联样式表 (CSS)、图像或其他 Facelets 页面。为了更好地处理这些关联文件,JSF 2.0 引入了 ResourceHandler API 供 JSF 组件和应用程序开发人员使用。

ResourceHandler API 定义了一种基于路径的资源打包惯例。在 ViewHandler 呈现一个视图并且浏览器解析完全呈现的页面后,浏览器资源请求就会包含在页面中。

为了处理与 JSF 页面分离的资源,FacesServlet 会调用 ResourceHandler.isResourceRequest() 方法来确定请求的是否为资源。如果该方法返回 true,FacesServlet 就会调用 ResourceHandler.handleResourceRequest() 方法来处理该资源请求。资源用 Resource 类对象表示。

资源处理标记

JSF 组件标记库为资源处理提供了以下标记。

标记 说明
h:head 提供 <head> 元素的标记。
h:body 提供 <body> 元素的标记。
h:outputScript 提供 <script> 元素的标记,最终提供脚本资源。
h:outputStylesheet 提供 <link> 元素的标记,最终提供样式资源。


应用程序开发人员可能会对资源提供器提供这些新资源处理标记时使用的编码感兴趣。h:head 元素提供开头的 <head> 标记以及该元素的属性(如果有)。接下来是提供要添加到 <head> 元素的资源。指定 h:outputScript 标记的 target 属性意味着将 <script> 标记添加到指定的目标,如 headbody。如果不指定 target 属性,则内联提供脚本,且不添加 <script> 元素。

结合使用 h:outputScripttarget 属性的好处是,页面下载时资源即添加到 JSF 文档,相对于将 JSF 资源添加到页面主体而言,这是一种可提高性能的优化。h:outputStylesheet 标记映射到 <link> 标记。

h:outputScript 标记的属性值在所提供元素的标记中编码。为 JavaScript 资源添加 <script> 标记需要设置以下属性。

属性
src 值取自资源对象,资源对象用 h:outputScript 标记的名称和 library 属性创建。
type 值取自资源对象。


样式表的不同之处在于不为 h:outputStyleSheet 标记提供 target 属性,因为 <link> 属性必须包含在 <head> 元素中,而 <script> 元素包含在指定的目标中。为样式表资源添加 <link> 标记需要设置以下属性。

属性
href 指定文档位置。值取自资源,资源用 h:outputStyleSheet 标记的 namelibrary 属性创建。
type 指定 MIME 类型,如 text/css。值取自资源。
rel 指定当前文档和链接文档之间的关系。即指定文本字符串的 stylesheet
media 指定显示链接文档的设备。即指定文本字符串的 screen


搭建环境

为了说明 JSF 2.0 中的资源处理,我们将创建一个由 input.xhtml 页面和 output.xhtml 页面组成的示例 Facelets 应用程序。

注:可从这里下载示例应用程序源代码。

我们将使用 Oracle JDeveloper 11.1.2,它为 JSF 2.0 提供内置支持,同时集成了 Oracle WebLogic Server 11g

  1. 首先,下载并安装以下软件:
     
  2. 然后,使用清单 1 中的 SQL 脚本在 Oracle Database 11g 快捷版中创建一个数据库表,以生成 JSF 数据表。可以使用不同于 OE 的示例模式。
CREATE USER OE IDENTIFIED BY OE;
GRANT CONNECT, RESOURCE to OE;

CREATE TABLE OE.Catalog(CatalogId INTEGER 
PRIMARY KEY, Journal VARCHAR(25), Publisher VARCHAR(25),
 Edition VARCHAR(25), Title Varchar(45), Author Varchar(25));
INSERT INTO OE.Catalog VALUES('1', 'Oracle Magazine',  
 'Oracle Publishing', 'Nov-Dec 2004', 'Database Resource  
Manager', 'Kimberly Floss');
INSERT INTO OE.Catalog VALUES('2', 'Oracle Magazine',   
 'Oracle Publishing', 'Nov-Dec 2004', 'From ADF UIX to JSF',  
'Jonas Jacobi');
INSERT INTO OE.Catalog VALUES('3', 'Oracle Magazine',   
 'Oracle Publishing', 'March-April 2005', 'Starting with  
Oracle ADF ', 'Steve Muench');

清单 1. 用于创建数据库表的 SQL 脚本

创建 Facelets 应用程序

input.xhtml 页面有一个 SQL 查询的输入域和一个用于提交 SQL 查询的 Submit 按钮。output.xhtml Facelets 页面包含一个由 input.xhtml 中指定的 SQL 查询生成的 JSF DataTable

  1. 为创建应用程序,在 Oracle JDeveloper 中选择 File>New
  2. 在 New Gallery 中,在 Categories 中选择 General>Applications,在 Items 中选择 Java EE Web Application,然后单击 OK
    注:可以使用其他应用程序模板,例如,开发 Oracle 应用开发框架 (Oracle ADF) 应用程序应选择 Fusion Web Application。
  3. 针对 ViewController 项目,在 Project Features 中选择 JavaServer Faces,如图 1 所示。
图 1. 选择 JavaServer Faces

图 1. 选择 JavaServer Faces

如图 2 所示,在 ViewController 项目的 Project Properties 中,应列出 JSF 2.0 库和 JavaServer Pages Standard Tag Library (JSTL) 1.2 库,因为创建 Java EE Web 应用程序时我们选择了 JSF 项目特性。


图 2. JSF 和 JSTL 库

  1. 因为我们在 JSF 2.0 (Facelets) 中使用的是默认视图定义语言,所以要为 JSF 页面创建 .xhtml 页面:
    1. 在 Application Navigator 中选择 ViewController 项目。
    2. 在 New Gallery 中,选择 Categories>Web Tier>HTML and Items>HTML Page
    3. 选择 Create as XML file,指定一个文件名 (input.xhtml),然后单击 OK,如图 3 所示。

图 3. 创建 .xhtml 页面

  1. 类似地,添加 output.xhtmlerror.xhtml Facelets 页面。

创建托管 Bean

  1. 针对 JSF 页面,创建一个托管 bean,也就是一个使用 @ManagedBean 批注进行批注的 POJO:
    1. 右键单击 faces-config.xml,这只是一个 JSF 2.0 空文件,然后选择 Open
    2. 选择 Overview 选项卡,然后选择 Managed Beans 节点。
    3. 单击 Add 添加一个新的托管 bean。
    4. 在 Create Managed Bean 对话框中,将 Bean Name 指定为 catalog,将 Class Name 指定为 Catalog,将 Package 指定为 view,将 Scope 指定为 request,选择 Annotations 选项,然后单击 OK
    托管 bean 类 Catalog.java(可下载的 zip)被添加到 ResourceHandler 应用程序。
  2. 在该托管 bean 中,指定以下 JavaBean 属性:inputText1、resultSetsqlQuery
    private ResultSet resultSet;
    private HtmlInputText inputText1;
    private String sqlQuery; 
    
  3. 为托管 bean 属性添加访问器方法。
  4. 添加操作方法 commandButton_action
    在此操作方法中,输入文本域中指定的 SQL 查询在 Oracle Database 中检索和运行,生成一个 ResultSet,其值在 resultSet 托管 bean 属性中设置。resultSet 属性的值与 Facelets 页面中的数据表绑定。托管 bean 类包括一个 createSQLQuery 方法,在 Facelets 应用程序变体中会用到它。

我们已用隐式导航分别在生成数据表和生成错误情况下导航到 output.xhtmlerror.xhtml。如果未给 JSF 页面操作或结果指定导航规则或导航条件,就会执行隐式导航。隐式导航使用以下结果值实现:

  • action 方法的返回值
  • h:commandButtonh:commandLinkUICommand 组件的 action 属性
  • h:linkh:buttonUIOutcomeTarget 组件的 outcome 属性
  • NavigationHandler API 的 handleNavigation() 方法

隐式导航意味着如果结果中未指定扩展名,则该结果将相同的扩展名用作当前 view id 的扩展名,导航到与该结果同名的 Facelets 页面(view ID)。

例如,对于结果值 output,如果 Facelets 页面 output.xhtml 与发起请求的 Facelets 页面位于同一目录中,则导航处理程序导航到 output.xhtml。如果请求来自扩展名为 .xhtmlview ID,则操作方法的结果可以指定为 outputoutput.xhtml/output.xhtml。如果 output.xhtml/output 文件夹中,则结果可以指定为 /output/output.xhtml/output/output,以便隐式导航到 output.xhtml

我们已用隐式导航将结果指定为 output。因此,导航处理程序导航到 output.xhtml

如果使用 Enterprise JavaBeans (EJB) bean,则可使用上下文和依赖注入 (CDI) @Named 批注,而不使用 @ManagedBean 批注。CDI 的优点是它统一了 EJB 和 JSF 编程模型,让 EJB bean 能够充当托管 bean,从而将事务支持引入 Web 层。

web.xml 文件

web.xml 文件包含 Faces servlet 以及该 servlet 对应的 URL 模式。

com.sun.faces.config.ConfigureListener 类添加监听器。com.sun.faces.config.ConfigureListener 用于分析配置资源和引导创建应用程序。javax.faces.VIEW_MAPPINGS 参数用于指定将具有指定扩展名的页面解释为 Facelets。可以使用 javax.faces.FACELETS_VIEW_MAPPINGS 参数代替 javax.faces.VIEW_MAPPINGSDEFAULT_SUFFIX 参数指定 URL 扩展映射的默认扩展。

web.xml 文件如清单 2 所示。

<?xml version = '1.0' encoding = 'windows-1252'?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
    <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xhtml</param-value>
    </context-param>
    <context-param>
        <param-name>javax.faces.VIEW_MAPPINGS</param-name>
        <param-value>*.xhtml</param-value>
    </context-param>
    <listener>
        <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
</web-app>

清单 2. web.xml 文件

faces-config.xml 文件

因为我们要使用 JSF 2.0 中的隐式导航特性和 @ManagedBean 批注来指定托管 bean,所以 faces-config.xml 文件是空文件。

<?xml version="1.0" encoding="windows-1252"?>
<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee">
  
</faces-config>

打包和呈现资源

本节将讨论 JSF 2.0 提供的两种资源打包模式:

  • Web 应用程序文档根目录中的 resources 文件夹,JDeveloper 中的 public_html 文件夹
  • 一个外部库,打包在一个 JAR 文件中并且包括在运行时类路径中

为了说明资源打包,input.xhtml Facelets 页面(包括在可下载的 zip 文件中)包括了一个使用 h:graphicImage 标记的 JPEG 图像。

<h:graphicImage library="images" name="logo.jpg"></h:graphicImage>

input.xhtml 页面(可下载 zip 文件中的 input1.xhtml)包括 h:outputLabel 组件用于生成标签、h:inputText 组件用于生成输入文本字段以指定 SQL 查询,以及 h:commandButton 用于提交 SQL 查询。h:inputText 字段已绑定到托管的 bean 属性 inputText1

output.xhtml 页面还包含一个 JPEG 图像,此外还包括一个 h:dataTable 元素,其值绑定到托管 bean 属性 resultSet,这是在输入字段中指定并用 Submit 按钮提交的 SQL 查询的 JDBC 结果集。h:dataTablevar 属性指定要用于循环访问数据模型的迭代变量,设置为 resultset。h:dataTable 内的 h:column 元素的值绑定到用 var 属性中指定的迭代变量来访问的 ResultSet 列值。

在文档根目录中打包资源

ResourceHandler API 使用基于路径的打包。JSF 2.0 中的默认实现是在 Web 应用程序文档根目录下 resources 文件夹的某个子文件夹中查找资源。

  1. 为打包示例应用程序中使用的图像资源,在 Web 应用程序根目录中创建一个 resources 文件夹,即 public_html 文件夹。
  2. resources 文件夹中创建一个 images 文件夹。
    images 文件夹代表一个资源库。
  3. 将图像 logo.jpg 复制到 images 文件夹。
  4. 从菜单中选择 View ->Refresh 刷新 Oracle JDeveloper 中的目录结构。

    input.xhtml 中包括下面的 h:graphicImage 标记:
    <h:graphicImage library="images" name="logo.jpg"></h:graphicImage>
    library 属性指定保存该徽标的目录的名称。name 属性指定图像 logo.jpg。Facelets 应用程序的目录结构如图 4 所示。

图 4. Facelets 应用程序的目录结构

  1. 接下来,在集成的 Oracle WebLogic Server 中运行 input.xhtml Facelets 页面:
    1. 右键单击 input.xhtml 并选择 Run

      JSF 2.0 应用程序得到部署,可以使用 URL http://localhost:7101/JSF2-ViewController-context-root/faces/input.xhtml 运行 input.xhtml 页面。h:imageGraphic 中的 JPEG 图像呈现,如图 5 所示。
       
    2. 指定一个 SQL 查询,如 SELECT * FROM OE.CATALOG,然后单击 Submit

图 5. input.xhtml 页面

图 5. input.xhtml 页面

    output.xhtml 页面使用隐式导航呈现,数据表显示出来,如图 6 所示。


图 6. output.xhtml 页面

将资源打包成 JAR 文件

为应用程序加载资源的另一种方法是使用 JAR 文件提供资源。JAR 文件需要添加到运行时类路径。JAR 文件中的资源必须使用基于路径的惯例在 META-INF/resources/<resourceIdentifier></span> 路径中打包。

  1. 创建如图 7 所示的文件夹结构。

图 7. 文件夹结构

图 7. 文件夹结构

  1. logo.jpg 复制到 images 文件夹。
     
  2. 使用 cd 命令更改 META-INF 文件夹之前的文件夹。
     
  3. 使用以下命令创建 JAR 文件。
    <jar cf resources.jar META-INF
    
  4. resources.jar 文件添加到项目中。
     
  5. 启动 Oracle WebLogic Server。

    resources.jar 文件应显示在 CLASSPATH 中,如图 8 所示。


图 8. CLASSPATH 中的 resources.jar 文件

如果服务器运行的所有应用程序都使用使用该图像资源,就要将该资源打包成 JAR 文件,并将其包括在服务器运行时 CLASSPATH 中,但如果只有该应用程序使用该资源,则只将它与该应用程序一起部署,如“在文档根目录中打包资源”一节所述。

添加样式表

针对其他类型的资源,如 CSS 文件、JavaScript 文件乃至其他 Facelets 页面(.xhtml 页面),可在 resources 文件夹中创建多个库。

  1. 作为另一个示例,在 resources 文件夹中创建一个 css 文件夹。
  2. 将清单 3 中的代码添加到一个 style.css 文件,然后将该文件复制到 css 文件夹。
    h1 {
        font-family: Helvetica, Geneva, Arial,
              SunSans-Regular, sans-serif }
    
      body {
        font-family: Georgia, "Times New Roman",
              Times, serif;
        color: purple;
        background-color: #d8da3d 
    }
    


    清单 3. style.css 文件代码
  3. 从 JSF HTML 组件面板中将一个 h:outputStylesheet 标记添加到 input.xhtml。
  4. 将库属性指定为 css,名称指定为 style.css。
    <h:outputStylesheet library="css" name="style.css"/>
    
    包含两个库(imagescss)的 resources 文件夹的目录结构如图 9 所示。

图 9. resources 文件夹的目录结构

图 9. resources 文件夹的目录结构

总结

本文讨论了 @ManagedBean 批注、隐式导航和资源处理等 JSF 2.0 特性,它们使 JSF 2.0 非常适合云环境。Java EE 7 将更新 JSF 规范,以应对与云相关的实际问题,如多承租方和伸缩性或横向伸缩。

本系列第二部分敬请期待,其中将探讨 Ajax 支持、视图参数、预导航、事件处理和可收藏的 URL。

另请参见

适用于云环境的 JSF 2.0,第 2 部分

 

JavaServer Faces 技术
云计算

 

作者简介

Deepak Vohra 是一名 NuBean 顾问、Web 开发人员、Sun 认证的 Java 1.4 程序员和 Sun 认证的 Java EE Web 组件开发人员。