首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Facelets 非常适合 JSF(5)

Facelets 非常适合 JSF(5)

传递子元素这里有一个关于 Facelets 的小秘密:复合组件基本上也是一类模板。所以,可以用 ui:define 标记传递模板参数,带上具体的 ui:insert,或者也可以把体作为默认 ui:insert 传递。
清单 8 就是字段组件的这样一种实现(field.xhtml):
清单 8.  field.xhtml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:z="http://www.qualcomm.com/jsf/core"
      xmlns:c="http://java.sun.com/jstl/core"
      xmlns:fn="http://java.sun.com/jsp/jstl/functions"
      xmlns:t="http://myfaces.apache.org/tomahawk">
THIS TEXT WILL BE REMOVED
<ui:composition>
          <!--  The label is optional.
                Generate it if it is missing. -->
        <c:if test="${empty label}">
            <c:set var="label" value="${fieldName}" />
        </c:if>
      
        <!-- The required attribute is optional,
                 initialize it to true if not found. -->
        <c:if test="${empty required}">
            <c:set var="required" value="true" />
        </c:if>
     
        <hutputLabel id="${fieldName}Label"
                      value="${label}" for="#{fieldName}" />         
        <h:inputText id="#{fieldName}" value="#{entity[fieldName]}"
                         required="${required}">
              <ui:insert />
        </h:inputText>
        <!--  Display any error message that are found -->
        <h:message id="${fieldName}Message"
            style="color: red; text-decoration: overline"
            for="#{fieldName}" />
</ui:composition>
THIS TEXT WILL BE REMOVED AS WELL
</html>




目前为止,清单 8 的工作基本上是不出所料。请注意 h:inputText 内部未命名  ui:insert 标记的使用。理解了它之后,就可以像清单 9 所示那样使用这个复合组件:
清单 9. 字段标记复合组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:a="http://www.arc-mind.com/jsf">
...
<h:form id="cdForm">
    <!-- Title, Artist, Price -->
    <a:field fieldName="title" entity="#{CDManagerBean.cd}" />
    <a:field fieldName="artist" entity="#{CDManagerBean.cd}" />
    <a:field fieldName="price" entity="#{CDManagerBean.cd}" >
        <f:validateDoubleRange minimum="15.0" maximum="100.0" />
    </a:field>
...




price 的字段标记被传递给验证器,作为匿名插入。因为其他字段没有定义体,所以匿名插入对于默认值没有影响。
传递动作在想传递动作绑定来创建像工具栏或导航列表这样的元素时,问题就是使用标准的表达式语言,不能传递,但是有方法可以做到!使用从对象中引用字段的相同方式,可以引用对象中的方法。所以,要创建可以创建动作绑定的组件,可以像下面这样做(来自 columnCommand.xhtml):
1
2
<h:commandLink id="#{action}" value="#{label}"
                              action="#{backingBean[action]}"/>




请研究动作属性的 value。请注意,我使用与前面从实体引用字段相同的方式,访问到了方法。可以用以下语法调用这个组件:
1
2
<a:columnCommand label="Edit" action="editCD"
backingBean="${CDManagerBean}"/>




这个调用把 CDManagerBean 的 editCD() 方法绑定到链接。清单 10 显示了 columnCommand.xhtml 的完整清单:
清单 10. columnCommand.xhtml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:z="http://www.qualcomm.com/jsf/core"
      xmlns:c="http://java.sun.com/jstl/core">
THIS TEXT WILL BE REMOVED
<ui:composition>
    <!--  The label is optional. Generate it if it is missing. -->
    <c:if test="${empty label}">
            <c:set var="label" value="${action}" />
    </c:if>
     
    <h:column>
        <f:facet name="header">
            <h:panelGroup>
                <hutputText value="#{label}" />
            </h:panelGroup>
        </f:facet>
        <h:commandLink id="#{action}" value="#{label}"
                                     action="#{backingBean[action]}"/>
    </h:column>
         
</ui:composition>
THIS TEXT WILL BE REMOVED AS WELL
</html>




Facelets 的不足我已经清楚地演示了使用 Facelets 的好处:即组件复合和模板框架,它的核心 是组件,而不是 Servlets 输出。但是采用 Facelets 也有些不足。其中之一就是,对 Facelets 的 IDE 支持极少。只有一个 Eclipse IDE 实现完全支持 Facelets(商业版的实现,请参阅 ),而且看起来还不支持代码补足。
而且也没对 Facelets 调试的 IDE 支持(也就是说,设置断点之类的东西)。要想调试,需要阅读 Facelets 手册,打开 JDK 1.4 样式的日志,根据开发情况设置它的 init 参数。
在有利方面来说,我发现使用 Facelets API 非常自然和直观。调试在开始的时候有些怪异,但是后来就适应了。随 Facelets 发行包提供的演示应用程序没有定制标记或功能的示例,但是核心项目代码中有,所以请用核心项目代码作为指导。
如果要使用新的 JSF 组件库,必须有公开这个库的 Facelets 标记库。有些主要的组件库(例如 Oracle 和 Tomahawk)的标记库存在,但是即使这些也需要调整。我必须调整 Tomahawk 标记库才能在应用程序中得到 Tomahawk 的日历组件。虽然编写导出组件的标记库文件比较容易,但是也是件麻烦事。如果想使用新的定制组件库,就必须编写标记库文件。
因为在其他实现中的问题,Facelets 看起来只能用于 MyFaces 1.1.1 和 Sun 1.2 JSF 的参考实现(Sun 的 JSF RI 1.2 还没有正式发布)。不能把 Facelets 用于 1.1 RI。虽然可以把 MyFaces 用于 IBM WebSphere,但不能把 Facelets 用于 IBM 的实现。(如果使用最新版本的 Facelets,必须使用最新构建的 MyFaces 1.1.2,它现在还没推出。)
还要注意的是,MyFaces 1.1 和 JSF RI 1.2 的底层机制不同。尽管如此,Facelets 试图把这两者的实现保持为它们当前的形式(MyFaces 1.1.2 和 JSF RI 1.2),这看起来解释了花在 Facelets 上的大量时间。如果双方更团结协调一点,让 Facelets 在两个环境中做同样的事上少花些时间,就可以把更多时间花在改进 Facelets 上。
返回列表