扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
1、JSF简介
JSF(Java Server Faces)体系结构是一种Web应用程序框架,它是首个Web应用程序开发的标准框架。JSF提供了一个基于组件的架构(框架)用于管理和构建Web应用程序接口,它也提供了丰富的功能集包含事件处理机制(Event Handling Mechanism)、页面导航(Page Navigation)、验证客户端数据(Input Validation)和数据转换(Conversion)等等。它同样也提供了基于组件的插件化体系来开发和展现用户界面组件,开发者可随时开发他们的自定义UI组件并很容易地将其应用到框架之中。JSF框架最主要的特色之一就是它并不仅针对于一种类型的客户端,意味着除了用于桌面的Html浏览器客户端外,它甚至还可能支持用于移动电话的Wml浏览器客户端。在这篇文章中,将对JSF框架和组成JSF框架的各种关键部件进行一个简单的介绍,接下来详细介绍JSF的请求处理生命周期的各种状态,然后提供一个简单的应用来示范其各种特性。
2、JSF基于组件的架构
在JSF出现之前,Servlets和JSP是在构成Web应用开发的核心组件中最主要的部分。我们来看看在一个传统的Web应用程序中所发生的交互作用,它的实现仅是由遵循MVC-2构架模型的Servlet和JSP组件来构建的。客户端(通常是一个HTML浏览器)发送请求到服务器,Web服务器收到请求,封装request然后通过来自客户端的各种参数值组装这个request对象并将其发送给Servlet。Servlet担当一个控制器(Controller),它解析接收到的request,然后与要执行各种各样的业务逻辑的Model(Java Beans)相结合,最后来选择一个要展现给用户的View。
就像Swing和AWT一样,JSF提供了一个基于组件的体系结构用于开发可重用的UI组件,使得你不需要去重复一些往往会发生在Model2体系结构的View部分的一些复杂的工作。这个框架不仅限于开发自定义的UI组件,同时也支持多种高级特性如之前提到的事件处理机制、验证来自客户端的用户输入数据和页面导航机制等。JSF的好处是表达各种各样的行为或属性的UI组件和它的呈现器(Randerer)之间的耦合度非常低,实际上几乎为零。因为用户与JSF应用交互时,它们其实是与呈现器的输出进行交互,取呈现器针对特定的客户端来创建特定的表现。有关Randerer在后面会有介绍。所以HTML浏览器并不是惟一的目标客户端应用,JSF应用甚至可能会在WML浏览器上也运行的很好。
JSF1.0平台完全符合JSR127标准,2.0的平台完全符合JSR(Java Specification Request)252标准规范。基于规范的内容,JSF2.0组件集包含服务端UI组件和事件发布模型、一套基本的UI组件、一个轻量级的依赖注入容器,规范的内容还包括可自动同步UI组件和应用程序对象、构建于Servlet AP之上,可与JSP一起使用,但并非完全依赖它等等。作为基于组件的构架,JSF具有很好的可配置性和可扩展性。正如开始提到的它具有插件化的体系,这使得JSF的很多功能都可以用可插入的组件替换。这种程度的可插入性让你在构建Web应用GUI方面得到相当大的灵活性,并且还可以很容易地将其它的一些基于组件的技术融入到JSF开发中。例如,JSF内置的轻量级的IOC框架,可以用更强大的Spring框架来取代。与先进的Web2.0技术相结合— 结合JSF与Ajax的优势来开发更加健壮的Web应用程序。
3、JSF基本原理
在JSF应用中,最重要的几个组件是:
◆UI组件:有状态的对象,有服务器维护,提供与用户的特定交互功能。UI组件是具有属性、方法和事件的JavaBean。它们被组织进一个视图,而该视图通常显示为一个页面的组件树。
◆托管①bean
◆验证器
◆转换器
◆事件和监听器
◆页面导航
◆呈现器
以上所述的所有组件都可以在单独的API包中找到。例如,UI组件在javax.faces.component包中,Validation API在javax.faces.validator包中等等。
3.1、UI组件
如果Java Swing的UI组件的展现是用于桌面Java应用程序,那么JSF UI组件则是用于Web应用程序。像Swing组件一样,它们构建在JavaBean规范和标准之上。这意味着JSF组件具有属性、方法和事件,如同传统的JavaBean中所具有的一样。JSF UI组件的特点之一就是它们可以管理组件的状态,更特别的是它们驻留在服务器端而不是户端,这是针对Web应用的约束做的一些特殊设计。很多内置的UI组件与JSF API绑定,如常用的Label,Text-Field,Form,Check-Box等等。JSF同时也提供了一套框架用于创建自定义的UI组件。
值得注意的是JSF UI组件仅表达一个组件的属性、行为和事件而并非实际的显示。例如,对于一个文本框(Text-Field),它的属性可以是文本框的值,可输入的最大字符数等等。修改文本框的现有的值或设置它的最大字符数将产生行为。改变文本框的值可能使得文本框触发某种事件的发生。这种形式即显示在客户端的文本框本身与UI数据呈现是相分离的。
这意味着有一个单独的组件,被称作Renderer,由它来负责UI组件在不同的客户端层面的显示,可能是运行在PC机上的HTML浏览器,也可能是运行在移动电话内部的WML(无线标记语言)浏览器。每个JSF组件都由一个惟一标识符来标识。
3.2、托管(Managed)bean
托管bean其实是一些遵循Java Bean规范的标准的Java类。一般地,托管bean被用来表达用户输入。它们甚至可能担当监听器(Listener)也可以处理适当的Action。
而我要向大家重点介绍的是,托管bean也是一个真正的IoC容器。当然,谈到IoC,大家肯定会想到目前比较流行的Spring框架,但还有另外两个实现了IoC的框架:HiveMind和PicoContainer,这是目前的三大IoC。
关于IoC就不作详细介绍了,但在这里列出它的几个核心的方面:
◆控制对象实例化并通过设置(setter)注入托管对象
◆依赖处理
◆支持对象生命周期管理
◆对于配置管理的支持
接下来,根据以上几点来解释JSF托管Bean同样也是一个“IoC”容器。
3.2.1、实例化控制
JSF的托管Bean工具提供了很好的解决方案来创建和实例化托管(Managed)Bean。
在JSF之前,要在页面中处理JavaBean,我们一般使用JSP的<jsp:usebean>标签,它允许我们在一个指定的scope中实例化JavaBean。JSF对JSP的这个特性做了很大的改进。使用JSF,你现在可以将任何一个含有无参构造函数的Java类,通过将其引用到一个XML配置文件faces-config.xml中注册为一个托管bean。例如一个Java类(或POJO),名为”User”并有name,phone和email三个字段:
|
我们现在可以将这个bean注册到faces-config.xml中:
<managed-bean> |
我现在可以随时在我的JSF应用中使用这个叫做“userBean”的bean。这个是通过JSF EL表达式来完成的。例如,将一个JSF UI组件绑定到userBean的一个属性上,我可以使用表达式#{userBean.name}作为一个JSF UI组件的参数值。现在,我将userBean的name属性绑定到一个JSF inputText UI组件上:
<h:inputText value="#{userBean.name}"/> |
现在,当组件的值改变时,userBean.name属性也跟着改变。如果userBean.name先改变也是一样。两者将自动保持同步,这是JSF的关键特性。
JSF托管bean的另外一个很重要的特性是它可以通过配置文件来初始化属性。比如说我现在可以通过在配置文件中增加额外的受管属性来为我的userBean定义一些初始的属性值。因此要为我的bean属性设置一些初始值,可以这样做:
<managed-bean> |
要看到这样做的效果,可以构建一个包含有几个被绑定到那些属性的文本框字段的JSF页面,在首次运行这个页面的时候,可以看到从配置文件中设置的一些初始值。
这是JSF的源代码,在一个表单中有几个被关联到userBean属性的输入框:
<h:panelGrid columns="2" > |
如果我们之前没有在faces-config.xml配置文件中设置email属性的初始值,表单中的Email字段值将为空。
关于受管属性的特性,另一个值得指出的是除了管理简单类型的属性,JSF的托管Bean功具还可以处理List和Map这样的属性。比如我可以添加一个”tasks”List到我的userBean中:List tasks;再添加一个setter和getter方法。然后我可以将其作为一个受管属性来初始化这个List。
<managed-property> |
要在运行的时候看到这些初始值,可以在JSP页面中添加一个dataTable组件:
<p>Current Tasks:</p> |
将Map定义为一个受管属性与管理一个List非常相似,除了是要指定map-entries而不是输入list值。如果Map属性在userBean对象被创建时为null,JSF将创建一个新的HashMap并组装它。否则,它会在现的的Map中直接添加条目。比如我现在在userBean中添加一个contactorsBlog的Map并增加setter和getter方法。
在faces-config.xml中这样来初始化我的contactors Map的属性:
<managed-property> |
在JSF页面中添加以下代码来显示contactorsBlog的初始化值:
<p>A few well-known blogs:</p> |
在这个例子中,Map的键和值都是String类型,但有的时候我们可能需要特殊的类型,如关键字是整数型,或者值是一个日期类型。为了支持这种情况,我们可能通过使用<key-class>和<value-class>元素将关键字和值转换为特定的类型。
除了将Map和List作为一个已存在的bean的受管属性,我们还可以将任何List或Map声明为托管Bean(不支持将数组声明为独立的托管Bean)。比如我可以在faces-config.xml文件中直接创建一个”toDo” List,这是完全定义在配置文件中的一个独立的List并且不是userBean的属性:
<managed-bean> |
注意,managed-bean-class是一个具体的”ArrayList”而不是”List”接口。
现在我们已经可以看到JSF托管bean对于控制实例化和初始化的强大之处了,接下来,我们将看到JSF是如何处理托管bean之间的依赖。
3.2.2、依赖处理
具有处理Java对象之间依赖关系的能力也是IoC必不可少的一点。尽管JSF不能处理循环依赖,但托管bean可能使用EL表达式相互引用。例如我可以将之前定义的ToDo托管bean引用到其它地方,例如userBean的tasks属性:
<managed-property> |
在这里需要指出的是,对于toDo托管bean与tasks属性的声明顺序是不需要关心的。不管被依赖的bean和调用bean在faces-config.xml文件中的声明顺序是怎样的,JSF托管bean工具都可以确保它是可用的。另外一个关于托管bean相互引用较重要的一点是,一个托管bean只能引用那些与它指定了相同的范围(scope)的bean,或者是生命周期比它自己长的托管bean。
3.2.3、生命周期
对于IoC必不可少的一点是对处理生命周期的支持。实际上JSF的托管bean工具对处理生命周期的支持做得非常好,因为它要求为HTTP request定义一个明确的生命周期范围,而在其它IoC容器中,对于这一点的处理则更一般。与在JSP UseBean标签中指定的范围参数类似,JSF有以下几种类型的生命周期范围:
none:这种类型的托管bean不会被存储在任何地方,只有当需要它的时候才被创建。
request:这种类型的bean只会将它的值存储在一个单独的请求的整段时期内,对于在同一对象上的并发请求,会实例化一个新的版本。
session:这种类型的bean会被存储在session中,意味着这个bean的属性在多个请求期间会一直存在。对象存储在session中无疑是线程安全的,并且如果不被应用程序显示的清除掉的话,当session过期后就会终止。
application:一个对象被创建为application范围,将在容器的整个生命周期内一直存在。
在JSF中,“page”范围是不可用的。这样做的目的是为了使托管bean不依赖于指定的页面。
下面给出各种scope的托管bean可引用到的范围:
托管Bean注册范围 |
只可引用的范围内的Bean |
none |
none |
request |
none,request,session.application |
session |
none,session,application |
application |
none,application |
3.2.4、配置支持
通过前面的一些例子,我们已经看到JSF托管bean是如何使用一个简单的XML文件来注册和实例化一些bean的属性的。功能强大并且操作起来也很简单,当然这样的工作只有当你希望去调用一些定制的应用逻辑时才有必要,否则JSF的主要工作是呈现一个Web UI到客户端并将其自动与一些托管对象保持同步。
4、结束语
在这篇文章中主要对JSF做了一些简单的介绍,并为了向大家证明JSF的托管bean也是一个真正的IoC容器的实现而做了更加详细的说明。JSF是一个优秀的框架,它具有很好的可配置性和可扩展性。例如Ajax4JSF就是将Ajax与JSF的优势相结合,使得Web应用中前端的开发变得更加容易,功能更加强大。市场上支持JSF可视化开发的工具也很多,如:Eclipse Web Tools、Oracle Jdeveloper 10g、Sybase WorkSpace、BEA Workshop等等,另外也有一些不错的对JSF现实的开源框架,如Apache 的MyFaces、ICESoft的ICEfaces、在Sun指导下开发的Facelets。在下篇文章中,将介绍JSF的其它的一些关键部件。如:
◆验证器
◆转换器
◆事件和监听器
◆页面导航
◆呈现器
注解:托管bean,在JSF的其它文章中亦称受管bean。英文原名Managed Bean。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。