前言
JavaServer Faces(JSF)是一种用于构建Java Web应用程序的标准框架(是Java Community Process规定的JSR-127标准)。它提供了一种以组件为中心的用户界面(UI)构建方法[1],从而简化了Java服务器端应用程序的开发。由于由Java Community Process (JCP)推动,属于Java EE5中的技术规范,而受到了厂商的广泛支持。
JSF提供了标准的编程接口、丰富可扩展的UI组件库、事件驱动模型等一套完整的Web应用框架。通过JSF可以在页面中轻松自如地使用Web组件、捕获用户行为所产生的事件、执行验证、建立页面导航等。
1 JSF体系结构
对大型Web应用来说,基本的组织和管理服务是必要的,但是它们也需要良好的结构。大部分web框架都遵循模型-视图-控制器(MVC)设计模式,JSF也不例外。
MVC模式(Model模型-View视图-Controller控制器)是软件工程中的一种软件架构模式。它把软件系统分为三个基本部分:(Model模型),(View视图)和(Controller控制器),在软件的角度看来,视图是表现层,它负责与用户进行交互。模型是业务逻辑和数据,而控制器则是响应用户事件和集成模型和视图的应用代码。JSF遵循MVC设计模式,这种架构确保了应用是松散耦合的,因而减小了层间的依赖性,提供应用程序的可维护性,其体系如图1-1所示。
图1-1:JSF系统结构图
(1)Model模型:“数据模型”(Model)用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。“模型”有对数据直接访问的权力,例如对数据库的访问。“模型”不依赖“视图”和“控制器”,也就是说,模型不关心它会被如何显示或是如何被操作。该层用于实现业务逻辑,JSF中一般使用JavaBean或EJB开发。其中JavaBean被称为Backing Bean。Backing Bean的创建与存储在配置文件faces-config.xml中指定,由managed bean机制来管理,被管理的Backing Bean称为Managed Bean。
(2)View视图:视图层能够实现数据有目的的显示。在视图中一般没有程序上的逻辑。JSF中的View层主要包括众多UI组件。组件为Java的Web应用带来了事件驱动风格,用户同组件的交互可能会激发一个事件,最终导致该组件或组件树中其它组件改变外观。开发者可以使用JSF内建或其他厂商提供的UI组件来开发View层。
(3)Controller控制器:控制器起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并做出响应。“事件”包括用户的行为和数据模型上的改变。Controller层位于View层与Model层之间,控制着它们之间的交互过程。该层主要包括名为Faces servlet的前端Controller Servlet、一个或多个配置文件faces-config.xml以及一系列action处理器[2]。Faees servlet负责从web客户端接收进入的请求,然后执行一组合理的步骤来准备和派发响应。
2 JSF的优势
JSF是Sun继JSP技术之后推出的又一项Java Web应用开发技术。JSP取得了巨大的成功,但也暴露出很多技术弱点。例如,在JSP中表示层和业务层都没有严格区分,JSP网页上HTML标签和Java代码混杂,使得大型Java Web应用的开发和维护十分困难。为此Sun决定制定一项新的技术标准,来支持组件化的UI设计,以弥补JSP技术的不足。JSF最重要的设计目标就是要简化Java Web应用的开发,主要有以下优势。
(1)UI组件(UI-component)
UI组件(UI-component)一直是桌面程序的专利,Web程序中,虽然HTML定义了基本的UI标签,但要使这些UI标签像UI组件那样工作,还需要很多代码片断来处理数据及其表现形式,而且有效地组织这些代码片断使其协调一致也是一件繁琐的工作。JSF将所有的用户界面元素抽象为UI组件,提高了代码的可重用性并极大地简化程序员的工作,例如,在页面上放置一个文本输入框,这个输入框立即具备了数据填充、界面更新、事件侦听、动作触发、有效性检查和类型转换的功能。更为重要的是,程序员只需根据业务逻辑编写核心业务代码,JSF会保证代码在合适的时候被执行,简化了开发。
(2)事件驱动模式
事件是面向对象方法的重要组成部分,对象之间通过事件进行沟通和交流,使得一个或多个对象能够对另一个对象的行为做出响应,共同合作去完成一项业务逻辑。通常,编写Web程序时,程序员要为对象之间的沟通设计机制,编写代码。虽然沟通的内容属于业务逻辑,但沟通的机制显然与业务没有太大关系,程序员因此为业务逻辑之外的功能浪费了时间。
JSF改变了这种状况。JSF的事件和侦听模式与大家熟悉的Javabean的事件模式类似,JSF的UI组件可以产生事件,例如,当页面上一个文本输入框的内容被修改时,会发出一个“值改变事件”。另一个对象如果对“值改变事件”感兴趣,只需注册为该对象的侦听者,并编写处理例程,即可命令JSF在事件发生时自动调用处理例程。JSF做了所有该做的事,留给程序员的只有业务逻辑代码的编写。
(3)用户界面到业务逻辑的直接映射
JSF实现了表示层和业务层的完全分离,但这并不意味着JSF将这两个层割裂开来,相反,表示层和业务层的沟通变得更直接和容易了。
举个例子,表单提交是Web编程最常见的任务,也是最复杂的任务之一。当用户在网页上点击“确定”按钮时,浏览器将生成一个HTTP请求,发往服务器端的某个Servlet,执行该Servlet的service方法。在service方法中,HTTP请求需要经历解码、类型转换、有效性验证、状态保存、数据更新等环节,处理这些环节的所有细节,对程序员来说是沉重的负担。
在JSF下,这些工作的很大一部分都由框架承担了,在程序员看来,这个过程是透明的,用户界面端的HTTP请求可以直接映射到后端的一个事件处理例程,JSF起到了承前启后的作用。
(4)Web开发的官方标准之一
JSF于2006年称为Java EE 5的组成部分,上升为Web开发的官方标准之一。Java EE 5最重要的使命就是简化Java的开发,而JSF无疑为这一使命立下了汗马功劳。同时, JSF技术已经得到了许多大厂商的支持,如Sun公司的JSF Web UI、IBM公司的JSF extension以及Oracle的ADF Faces等,许多开源项目也提供对JSF技术的支持。同时Oracle、Sun、Borland和IBM等公司都为JSF提供了开发环境。
JSF还有其他很多优势,比如集中式页面导航、清晰的角色分工、表示层和业务层的分离等,使JSF表现出其旺盛的生命力。随着JSF技术的不断成熟和版本更新,其必将获得越来越多的应用。
3 JSF应用实例
Web层与客户端进行交互,接收客户的请求并对其请求进行响应和验证,根据请求内容,将其交给业务层中的相关EJB构件进行处理,最后将处理结果返回给客户端浏览器并展示给用户。本系统中,Web层使用JSF技术来实现。JSF是一个可重用、可扩展、基于组件、工具友好的服务器端UI框架,是一种标准的J2EE表示层的技术,JSF框架完全遵循模型-视图-控制器(MVC)模式设计。JSF提供了可重用并可扩展的用户界面组件,使得Web页面的开发更方便、快捷。
利用JSF提供的组件快速构建的JSP页面可以大大提高了开发速率;使用FacesServlet作为控制器(Controller)来管理JSF的请求处理周期,每个JSF请求都要通过FacesServlet,使得应用层的开发变得比较规范而且易于维护。若要使用JSF的这些功能,首先需要在Web.xml中添加以下配置:
…
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/faces-config.xml,/WEB-INF/navigation.xml </param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
…
其中javax.faces.CONFIG_FILES用于配置JSF中使用的相关配置文件的位置,而servlet的配置则是使*.faces结尾的请求都会由FacesServlet的控制。
JSF提供托管Bean(Managed Bean)机制来管理后台Bean(Backing Bean)。后台Bean是指与一个或多个JSF视图层UI组件相联系的JavaBean。可以通过WEB-INF/faces-config.xml文件来配置一个后台Bean为托管Bean,其配置如下:
<faces-config>
<managed-bean>
<managed-bean-name>personFace</managed-bean-name>
<managed-bean-class>
hdty.project.system.face.PersonFace
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean></faces-config>
JSF页面组件一般都与后台Bean绑定,这样能使我们更好的控制组件的属性。JSF后台Bean的主要功能有两种:一是为页面组件提供数据,同时接受页面输入数据并验证,二是调用业务层中的会话Bean。而且,后台Bean不需要依赖于JavaServer Faces API(例如UI组件类),使得表示层和模型层能够更好的分离。
当一个后台Bean被定义为托管Bean后,JSF的托管Bean机制就会负责被托管的后台Bean的实例化,当WEB应用需要访问某个托管Bean时,托管Bean机制会自动生成一个实例,供Web应用使用,而无须程序员代码的介入。
JSF默认使用faces-config.xml来定义导航规则,这里在Web.xml中配置使用navigation.xml文件来定义导航规则。统一的导航使得页面的流转非常容易,在配置文件中定义规则后,只需要在按钮或链接的action属性中指定得出的字符串结果,这个字符串就是系统选定的导航规则。复杂的应用则需要开发人员编写动作(action)方法,在一定的数据处理或计算后,得到需要显示的数据或下一个要显示的页面。导航配置方法如下:
<navigation-rule>
<from-view-id>/hdty/project/system/personInsert.jsp</from-view-id>
<navigation-case>
<from-outcome>inserted</from-outcome>
<to-view-id>/hdty/project/system/personList.jsp</to-view-id>
<redirect />
</navigation-case>
</navigation-rule>
后台Bean调用可以调用中间层的一些方法来进行业务处理。这里我们使用EJB中间件技术作为中间层,则后台Bean可以调用EJB容器中的会话Bean,在实现上也比较简单。在调用会话Bean中方法之前,我们先要查找上下文,找出需要的会话Bean,然后调用相关方法。示例代码如下:
public class StandPorcessService {
private StandPorcess imp; //定义执行器接口
public BP_ExecuteService (){ //构造函数
//初始化上下文,通过远程接口调用EJB
InitialContext ctx = new InitialContext();
imp =( StandPorcess)ctx.lookup("StandPorcessBean/remote");
}
public List getStandsBean List(){…}//得到标准列表
……
}
该工程我已经上传至googlecode以便大家下载和学习使用,使用SVN下载地址为http://my-project-wangz.googlecode.com/svn/trunk/ my-project-wangz-read-only,项目名称为JSF_Demo_persons,如果遇到任何问题,请与我联系,6937365@qq.com
参考文献
[1] Mann, K. JavaServer Faces in Action[M]. A1bazaar, 2005
[2] 付明腾.基于JSF和EJB3.0的Web应用研究[D].武汉理工大学,2008