实现图形JSF组件

来源:百度文库 编辑:神马文学网 时间:2024/04/23 19:57:38
开发人员认为,如果有合适的工具来创建交互式Web界面,他们就能将时间集中在核心需求和定制上,并在规定时间内及时得交付应用程序。与其他技术如JavaServer Pages或Apache Struts 相比,JavaServer Faces (JSF)技术为创建交互式Web应用程序带来了很多便利。JSF在程序逻辑和GUI表示之间划出一条清晰的界限,提高了对Web程序的维护能力,并为Web用户界面组件的开发和重用提供了一个框架。
如今,许多Web应用程序开发人员都在转而使用JSF,但是他们发现,预先定制的JSF UI组件受到基本DHTML窗口部件的限制。监管或业务流程监控之类的高级应用程序需要能与JSF框架兼容的高级可视化组件。JSF框架的标准化使它易于开发能够重用的自定义Web GUI组件。另外,Web组件开发商现在能提供更复杂的组件,并承诺Web应用程序开发人员能够轻松地使用这些组件。此类JSF用户界面组件必须集成并部署到JSF运行时框架中去,并在其中完全展开,还必须在设计时很好地集成到提供JSF支持的IDE中去。
尽管JSF带来了标准用户界面框架,但对于开发第一个自定义JSF组件而言,还是存在几个缺陷和漏洞。让我们看看怎样创建一个纯HTML无法轻松创建的图形JSF组件。图形JSF组件的特点不仅要求生成DHTML,而且还需要对图像生成和客户端交互提供补充支持。我们将以一个图形组件的例子来阐述这些特点。该图形组件能够提供曲线图,并为各种客户端导航和交互提供便利。我们还会了解到将该图形组件集成到JSF-enabled IDE中所需要的步骤。通过理解图形组件的设计方法,您将会更好地理解如何实现JSF组件,而这应该能使您开发出定制的JSF图形组件。
什么是JSF?
JSF是一种能够简化Web应用程序表示层结构的标准服务器端框架。定义JSF框架的JSR 127(参见参考资料)带有一个能提供基本UI组件(如输入栏和按纽)的参考实现。您可以将可重用用户界面组件集中起来创建Web页,将这些组件绑定到应用数据源上,并用服务器端事件控制程序处理客户端事件。根据说明书介绍,组件供应商能编写与JSF运行时框架集成的组件,并将其集成到在设计时与JSF兼容的IDE中去。
从很大程度上讲,JSF组件同在HTML 2.0技术要求下可用的HTML组件和标签直接相符合。对许多Web应用程序而言,这套相对简单的组件是够用的。然而,许多应用程序如监管或监控程序需要更复杂的数据显示与交互,比如制表、制图和映射。由于JSF组件在HTML中直接提交复杂图形小部件的能力有限,所以设计这些高级组件的能力并不突出。解决方案要求服务器端组件向客户传输图像,却会给自身带来问题,因为在基本HTML图像上进行交互要受到限制。最后,使用JavaScript时,必须能调用客户端交互来使用户能对数据进行导航和交互。
让我们看看开发一个简单的、将CSS输入HTML页面的JSF组件需要哪些步骤。当开发高级JSF图形组件时,这一简单组件的描述和代码样本会作为背景。图1显示了如何使用即将开发的组件,并显示将要得到的结果。使用这种组件的好处是能够通过改变某个JSF动作的组件值,来改变整个页面的外观。

图1:显示了我们如何使用一个非常简单的JSF组件将CSS输入某个HTML页面并得出结果。
开发组件
JSF组件包含若干个Java类和配置文件。为创建一个自定义JSF组件,您需要开发一个扩展JSF基本组件类的Java类;为默认呈现软件包开发呈现程序;开发一个将在JSP页面中用于描述标签的Java类;编写一个标签库定义(TLD)文件;编写JSF配置文件。让我们更深入地了解这5个步骤。
开发组件Java类。组件类负责管理代表组件状态的属性。因此,我们必须根据组件的行为(如输入组件或输出组件),给组件选择适当的基类(参见清单1)。这里描述的组件可进行扩展javax.faces.component.UIOutput,以显示指向某个样式表文件的URL,或内联式样式表的内容。该组件可用于在JSF动作中将某个样式表转换成另一个样式表。关联属性规定着值的类型:要么是一个URL,要么是内联样式。该组件还必须能够在向服务器发送请求期间,使用经过JSF框架处理的对象,来存储并修复自己的状态。组件的状态由重建对象所需的重要属性值组成。JSF框架自动调用saveState()和restoreState()方法,我们可以在组件中实现这两种方法来达到这一目标。
清单1. 组件类管理显示组件状态的属性。可依据组件的行为,为其选择一个适当的基类。在本例中,该组件扩展javax.faces.component.UIOutput,以显示指向某个样式表文件的URL,或者某个内联式样式表的内容。
import javax.faces.component.*;public class CSSComponent extends UIOutput { private Boolean link; public String getFamily() { return "faces.CSSFamily"; } public boolean isLink() { if (link != null) return link.booleanValue(); ValueBinding vb = getValueBinding("link"); if (vb != null) { Boolean bvb = (Boolean) vb.getValue( FacesContext.getCurrentInstance()); if (bvb != null) return bvb.booleanValue(); } return false; } public void setLink(boolean link) { this.link = new Boolean(link); } public Object saveState(FacesContext context) { return new Object[] { super.saveState(context), link }; } public void restoreState(FacesContext context, Object stateObj) { Object[] state = (Object[]) stateObj; super.restoreState(context, state[0]); link = (Boolean) state[1]; } }
开发呈现程序。呈现程序有两个作用。第一,呈现程序负责发送适当的HTML程序段,该程序段能在客户端中呈现组件。通常情况下,这个HTML程序段由一些适于呈现整个Web浏览器的HTML标签组成。此JSF生存周期称作编码阶段或呈现—响应阶段。该响应阶段还能发送增强客户端交互性的JavaScript代码。
呈现程序的第二个作用是解析来自客户端的数据,从而对服务器端的组件状态进行更新(如用户在文本字段输入的文本)。标准呈现程序软件包具有强制性,但也可以提供其他呈现程序软件包,用于提供可替换的客户端表示法或SVG之类的语言(参见参考资料)。通过检验组件的连接属性,您实现的呈现程序(参见清单2)将选择在HTML页面中发送的CSS样式。
清单2. 标准呈现程序软件包具有强制性,但是,您可以使用其他呈现程序软件包,来提供可替换的客户端表示法或语言。通过检验组件的连接属性,您实现的呈现程序将选择在HTML页面中发出的CSS样式。
import javax.faces.component.UIComponent;import javax.faces.context.FacesContext;import javax.faces.context.ResponseWriter;import javax.faces.render.Renderer;public class CSSRenderer extends Renderer {public void encodeEnd(FacesContext context,UIComponent component) throws IOException { super.encodeEnd(context, component); if (component instanceof CSSComponent) { CSSComponent cssComponent = (CSSComponent) component; String css = (String)cssComponent.getValue(); boolean isLink = cssComponent.isLink(); if (css != null) if (isLink) context.getResponseWriter().write( ""); else context.getResponseWriter().write( "