跳至内容 Java Solaris 社区 Sun 商店 加入 SDN 我的个人档案 加入的益处
 
如何编写 JavaServer Faces 组件
作者:Tor Norbye,2005 年 7 月  
当您对 JavaServer Faces 组件有了更多的了解后,很可能希望编写自己的组件。尽管您可以按预期的方式使用自己的组件,但还可以采取一些具体的方法来确保这些组件能够很好地与 Java Studio Creator 等工具配合使用。此技术提示将向您说明这一点。您会发现,这些相同的方法还可以确保您的组件能够很好地与层叠样式表 (Cascading Style Sheets, CSS) 结合使用。
 
背景信息

为了更有效地掌握下面的信息,您应该熟悉 JavaServer Faces 组件、组件标记以及编写它们的方法。有许多文档都是针对这个主题而编写的,在您继续阅读本文章之前,可能需要参考这些文档。建议您最好从编写定制组件,第 1 部分:开发组件库开始阅读。

编写 JavaServer Faces 组件并不困难,您需要编写 3 到 4 个定义该组件的类:1 个接近于组件功能的标准 UIComponent 的子类、1 个呈现子类,以及 1 个用于驱动呈现响应阶段的标记处理类。您还需要编写一个 .tld 文件(标记库描述符文件,它是一种描述标记库的 XML 文档)和包含组件相关信息的元数据文件(如 faces-config.xml)。

要遵循的四条重要规则

在编写自己的 JavaServer Faces 组件时,需要遵循四条规则。遵循了这些规则,您可以确保在使用 CSS 属性调整了组件的大小和位置后,该组件可以正常发挥作用。它们还可以确保在设计阶段,这些组件能够很好地在 Java Studio Creator 之类的工具中使用。下面将按照重要性的优先顺序来介绍这四条规则:

规则 1:使用 ResponseWriter 类的方法 startElementendElementwriteAttribute

最重要的是:必须使用 ResponseWriterstartElementendElementwriteAttribute 方法,而不是使用 write 方法。不能简单地通过 write 方法以流的方式线性输出 HTML 字节来编写标记,这一点至关重要。

但是,此规则有一个出现机率很小的例外情况:那就是某些组件需要生成用户提供的 HTML 输出。在这种有限的情况下,您可以使用 write 方法。例如,如果将 HtmlOutputText 组件的 Escape 属性设置为 false,则此例外情况适用于该组件。

规则 2:始终将组件引用传递给 ResponseWriter 中的 startElement 方法。

始终将组件引用传递给 ResponseWriterstartElement 方法是至关重要的。例如,如果 UIComponent 是一个 PanelGrid,并且您要生成 <table><tr><td>...作为输出,则应该将以下内容传递给 startElement

writer.startElement("table", gridpanel);
writer.startElement("tr", gridpanel);
writer.startElement("td", gridpanel);

规则 3:为每个组件使用一个样式属性。

每个组件都应具有一个样式属性,该属性用于对所呈现的 HTML 标记呈现样式属性。当具有了样式属性,Java Studio Creator 等工具就可以使用样式表来调整组件的大小和位置。

请记住,复制所呈现的顶级 HTML 标记的样式属性是至关重要的。遗憾的是,实际情况并非简单,您应该记住以下三种可能出现的复杂情况并采取应对措施来避免出现问题:

  • 呈现单个顶级的 HTML 元素 - 通常,您使用 JSP 标记来呈现单个顶级的 HTML 元素(甚至可能包含子级元素)。在本例中,只需将 JSP 标记的样式属性值复制到顶级 HTML 标记属性中即可。例如,如果 JSP 中包含
    <h:commandButton style="width: 100px"/>
    ,则会呈现
    <input type="submit" style="width: 100px"/>

  • 呈现多个顶级的 HTML 标记,但只有一个可视标记 - 如果您需要呈现多个顶级的 HTML 标记,但只有一个标记是可视标记,则应该复制该可视标记的样式属性。例如,组件可能要先呈现 <script> 标记,然后再呈现它的一个可视元素,即 <table> 标记。呈现 <table> 标记后,组件可能会呈现另一个非可视元素,如类型为 hidden<input>。在本例中,您只需发出 <script>,然后发出 <table>(其 style 属性值来自 JavaServer Faces 组件),最后发出类型为 hidden 的 <input> 即可。

  • 将多个可视元素呈现为同等顶级元素 - 如果必须将多个可视元素呈现为同等的顶级元素,则需要将这些元素包装在单个容器组件(如 <span><div>)中。请务必将样式属性只放在外部组件级别上,从而包装 <span><div>。还请注意,只有当呈现的所有子元素都是内联元素时,才应该使用 <span> 容器组件。

规则 4:切勿从呈现器中抛出异常!

请务必不要从呈现器中抛出异常。例如,即使某个值是一个必需的属性,也不要只因为呈现的值为 null 而抛出配置异常!如果您确实需要组件向用户提示出现了问题,我认为可以在运行期间使用该组件时抛出异常。但在设计时,组件尚未正确配置是很正常的。例如,用户可能刚将组件放在页面上,正准备对其进行配置。

如有必要,可以在呈现器中添加代码来检查设计时是否使用了组件呈现器。代码应如下所示:

if (java.beans.Beans.isDesignTime()) {
	// Designtime - better render error handling here
	...
}else{
	// Runtime - throw your exceptions if you must
	...
}

您要考虑的一件事是如何让组件如实地向用户呈现问题消息。例如,在 Java Studio Creator 中,如果您放置了消息组件,该组件会提示您是否需要与任何项进行绑定(因为 for 属性为 null,所以尚未配置该组件)。

编写组件后,应对其进行包装,这样就可以轻松地将其导入 Java Studio Creator 并随时使用它。组件库文章为 Java Studio Creator 创建 JavaServer Faces 组件库中介绍了有关如何进行包装的内容。

作者简介

Tor Norbye 是 Sun Java Studio Creator 开发团队的高级工程师,他负责编写可视 Web 页面设计器和页面导航编辑器。在从事 Java Studio Creator IDE 的开发工作之前,他还参与过 Sun C/C++ 调试器和 Emacs 集成的工作。他会定期更新自己撰写的有关 IDE 和相关主题的博客文章

更多的开发者资源

有关为开发者提供的更多技术提示、文章和专家建议,请访问 Sun Developer Network (SDN) 上的 Java Studio Creator 开发者资源,网址为 http://gceclub.sun.com.cn/prodtech/javatools/jscreator/