深入浅出JBoss_Seam

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

深入浅出JBoss Seam
作者Michael Yuan译者包亮发布于 2007年11月2日上午1时3分
社区
Java
主题
Web框架
标签
JBoss Seam,
JBoss,
EJB,
JSF
本文节选了Michael Yuan和Thomas Heute所著的即将出版JBoss Seam: Power and Flexibility Beyond Java EE 5.0第一章和第二章,内容有所删减。

相关厂商内容
免费迷你书下载:深入浅出Struts 2
活动:体验基于OpenSolaris的Web/企业应用(8.30 杭州)
SOY Framework:Java富客户端快速开发框架
Hadoop中的集群配置和使用技巧
免费迷你书下载:Grails入门指南
相关赞助商
InfoQ中文站Java社区,关注企业Java社区的变化与创新,通过新闻、文章、视频访谈和演讲以及迷你书等为中国Java技术社区提供一流资讯。

什么是Seam?
JBoss Seam是“Java EE 5.0的一个轻量级的框架”。

这是什么意思?难道Java EE(Enterprise Edition) 5.0本身不是一套“框架吗”?为什么在官方规范之外,还需要另外一个框架?好吧,我们就将seam看作是本应该被包括在Java EE 5.0中的一个“遗漏的框架”吧。

它在Java EE 5.0框架的上层,为所有的在企业Web应用中的组件提供了一个统一的、易于理解的编程模型。

它同样使基于状
态的应用和业务流程驱动的应用的开发易如反掌。

换句话说,Seam致力于开发者生产力和应用扩展性。

1. 整合和强化Java EE框架
Java EE5.0的核心框架是EJB(Enterprise JavaBeans)3.0和JSF(JavaServer Faces)1.2。

EJB 3.0(以下简称EJB3)是基于一个POJO(Plain Old Java Objects)的业务服务和数据库持久化的轻型框架。

JSF是一个基于
MVC(Model-View-Controller)的Web应用框架。

大多数的Web应用都将包含有业务逻辑的EJB3组件和Web应用前端显示的JSF组件。

EJB3和JSF虽然互补,但是他们是根据各自的理念设计的独立的框架。

例如,EJB3使用注解(annotation)来配置服务,而JSF使用的是XML文件。

更进一步讲,EJB3和JSF组件在框架层面上是互不敏感的。

要整合EJB3和JSF,开发者必须手动地构造facade对象(如:JSF支持bean),将业务组件与Web页面和样板代码(又称plumbing代码)联结起来,以便能跨框架调用方法。

将这些技术粘合起来是Seam的职责之一。

Seam打破了EJB3和JSF之间的人工层,它为整合EJB3和JSF提供了一个一致的,基于注解的途径。

只需要个别简单的注解,Seam中的EJB3业务组件就能直接被用来支持JSF Web表单或者处理Web UI事件。

Seam允许开发者将“同一种东西”——有注解的POJOs——应用与所有的应用组件。

与其他Web框架开发的应用相比,Seam应用概念简洁,同样的功能却需要较少的代码(在JAVA和XML 中)。

如果没有耐心,或者想要快速预览,一个Seam到底有多简单,你可以现看看本文描述的hello world一例。

在JSP来说困难的任务,Seam可以轻易的完成。

例如,JSF头疼的一个问题就是过分依赖HTTP POST。

这使得将一个添加到书签中的JSF网页,通过HTTP GET 访问相当困难。

但是有了Seam,生成一个REST网页是非常容易的。

Seam提供了一系列JSF组件标签和注解,增加了“web友好”和JSF应用的网页效率。

同时,Seam拓展了EJB3到POJO的组件模式, 从web层到业务层都有了状态上下文。

进一步说,Seam整合了一系列主要的其他开放源代码框架,例如jBPM、JBoss Rules(又名Drools)、JBoss Portal、JBoss Microcontainer等等。

Seam 不仅能将它们“有机结合”起来,而且可以像整合JSF和EJB3一样强化原有的框架。

Seam位于Java EE 5.0底层,但它的应用并不局限与Java EE 5.0服务器。

一个Seam应用可以部署在J2EE 1.4应用服务器和Tomcat服务器上。

这意味着现在能在Seam应用中得到产品化支持。

1 + 1 > 2
或许有这样一种误解,认为Seam仅仅是将各种不同框架串起来的另外一个集成框架。

Seam提供了它自身管理的状态上下文,允许框架通过注解和EL(表达式
语言)表达式与其他框架进行深度整合。

整合的程序来自于Seam开发者对第三方框架的认知。

2. 一个为ORM设计的Web框架
对象关系映射(ORM)解决方案在当今企业应用中广为使用。

但是,大多数当前的业务和web框架并不是为ORM设计的,它们并不在整个Web交互生命周期——从请求来临到响应完成——管理持久上下文。

这就导致了包括可怕的LazyInitializationException在内的各种ORM异常,带来了如“数据传输对象(DTO)”等丑陋的伎俩(ugly hacks)。

Gavin King发明了Seam,同时他也发明了在世界上广为使用的ORM解决方案Hibernate。

为了继承和发扬ORM的最佳实践,Seam进行了重新设计。

有了Seam,就不必再写DTO,你所做的就是延迟加载。

因为扩展后的持久上下文就如同一个自然的高速缓存,可以减少和数据库的交互,ORM的性能就会被极大地改进。

进一步讲,因为Seam整合了ORM层、业务层和表示层,开发者就能够在表示层直接展示ORM对象,也能把数据库验证注解用于输入表单,以及重新定向ORM
例外到定制的错误页面。

3.专为有状态Web应用而设计
Seam是专为有状态Web应用而设计的。

Web应用是天生的多用户应用,电子商务应用天生也是有状态的和有事务的。

但是,大多数已有Web应用框架是面向无状态应用的。

开发者必须操作HTTP会话(session)对象来管理用户状态,与核心业务逻辑无关的代码不仅会混乱你的应用,而且带来了一系列的性能问题。

在Seam中,所有的基础应用组件天生地有状态。

它们使用起来要比HTTP session 容易,因为它们的状态由Seam公开管理。

没有必要在Seam应用中编写引起麻烦的状态管理代码——只需在其组件上注解其做用域、生命周期方法以及其他状态属性,Seam就会掌管其他[译者注:指这些组件的生命周期]。

Seam状态组件要比HTTP会话(session)能更好的管理用户状态。

例如,你能有多个“会话”进行,每个“会话”由在一个HTTP会话(session)中一系列的Web请求和业务方法调用组成。

进一步说,在Seam中,数据库缓存和事务能自动与应用的状态相连。

Seam在内存中自动保存数据库更新,等到对话结束后提交到数据库。

内存中的缓存能大大减轻复杂状态应用中数据库的负载。

除了以上这些,Seam支持整合开源JBoss jBPM业务程序引擎,大大提升了Web 应用中的状态管理。

你现在能为一个机构中不同工作人员(诸如客户、经理、技术支持人员等等)的指定工作流程,利用工作流程来驱动应用,而不是依赖用户界面事件处理和数据库。

4. 支持Web 2.0
Seam为Web2.0应用进行了充分的优化。

它给AJAX(异步JavaScript和XML,增加网页交互的一种技术)提供了多种支持——从内置“零Javascript”的AJAX组件到有AJAX支持的JSF组件,再到定制的JavaScript库,Seam为浏览器端的Javascript对象提供了直接访问Seam服务器组件的途径。

Seam提供了一个先进的并发模型,有效的管理来自同一用户的多个AJAX请求。

对于AJAX应用,不断增长的数据库负载是一个巨大的挑战。

与一个非AJAX应用相比,一个AJAX应用要向服务器发送的更频繁的请求。

一但数据库必须响应这些AJAX请求,那么数据库就不堪重荷。

Seam中的状态持久上下文正如一个内存中的缓存,它能在会话始末保存信息,最终帮助减少数据库交互。

Web2.0应用往往为其数据使用复杂关系模型(例如,一个网络交际站点所做的就是处理和显示“用户”之间的关系),对于这些站点,延迟加载对于ORM层至关重要。

否则,一个简单的查询就能级联地加载整个数据库。

正如我们前面所讨论过的,Seam是现今唯一一个正确支持Web应用延时加载的Web框架。

5.依赖双向映射的Pojo服务
Seam是一个“轻量级”框架,因为它使用POJO(plain old Java objects)作为服务组件。

在应用中,POJO没有使用接口或抽象类来"钩住"组件。

当然,问题是如何使POJO交互来组成这个应用?它们如何与容器服务(例如,数据库持久化服务)交互?
Seam通过使用一个流行的、被称作依赖注入(DI)的设计模式联结所有POJO组件。

在这个模式下,Seam框架管理着所有组件的生命周期。

当一个组件需要使用另外一个时,它通过注解(annotation)向Seam声明此依赖。

Seam依据应用当前状态得到这个依赖组件,并将它注入到所需求的组件中。

通过拓展依赖注入概念,一个Seam组件A不但可以构造另外一个组件B,而且把此组件B“抛还”给Seam以备其他组件(例如组件C)以后使用。

这类双向依赖管理甚至都广泛的应用于简单的Seam web应用中(例如第二章的hello world一例)。

在Seam术语中,我们称这个为“依赖双向映射”。

6.非常规的配置
[译者注:指以隐式映射为主题,以显式映射为例外的配置方式]
使Seam易用的主要设计原则是“非常规的配置”。

其思想是为这些组件提供一系列默认行为,开发者只需要在预期行为非默认的时候,显示地配置组件。

例如,
当Seam将组件A作为属性注入到组件B时,默认地,组件A刚会以组件B被注入的属性的名称命名。

Seam里还有很类似的细节。

总的结果是Seam中配置元数据要比其他Java框架简单的多。

因此,大多数的Seam应用能通过一系列简单的Java注解进行充分配置。

开发者从减化的复杂度中受益匪浅,最后,与其他Java 框架相比,用更少的代码实现同样的功能。

7.避免滥用XML
或许你已经注意到,Java注解在表述和处理Seam配置元数据时扮演着重要的角色。

通过这样的设计使框架更易于操作。

在J2EE发展早期,XML曾经被看作配置管理的“圣杯”。

框架设计者将所有的配置信息,包括Java类和方法名称都统统丢进XML文档,而不考虑对开发者所带来的后果。

反省后,发现这是个严重的错误。

XML配置文档太过重复。

开发者必须重复代码中已有的信息,从而将配置和代码联结起来。

这些重复使应用易于出错(例如,一个拼写错误的类名可能在运行时显示为一个难于调试错误)。

缺少合理的默认配置进一步使这一问题复杂化。

事实上,在一些框架中,相当数量的样板代码伪装为XML,可能相当于或者超过实际应用中JAVA代码的数量。

对于J2EE开发者,XML的滥用通常被称为“XML地狱”。

Java社区认识到了XML的滥用问题,并且已经非常成功地用Java代码中的注解取代了XML。

EJB3是Java官方标准化机构促进Java企业组件中注解使用的一项成果。

EJB3完全可选择的使用XML文档,它向正确方向迈出了积极的一步。

Seam 加入了EJB3的注解,为整个web应用拓展了基于注解的编程模型。

当然,XML对于配置数据并非完全不利。

Seam设计者认识到XML适用于指定页面流程或者定义业务流程的web应用。

XML文档使开发者集中地管理整个web应用的工作流程成为可能,同时也反对将配置信息分散于java源文件中。

工作流程很少能与源代码耦合,因此XML文档中并不需要重复键入已存在于代码中的信息。

8.为测试而设计
Seam为了易于测试而重新设计。

因为所有的Seam组件都是注解过的POJO,它们易于进行单元测试。

开发者仅仅通过利用常规的Java new关键词来构造实例,然后在测试框架(例如JUnit 或者TestNG)中运行任何方法。

如果需要测试多个Seam组件的交互,开发者则逐个实例化这些组件,然后手动建立它们的相互关系(也就是显示地使用setter 方法,而不是依靠Seam依赖注入功能)。

集成测试整个Seam应用比较复杂,因为开发者必须在Seam容器中运行应用。

Seam 用嵌入的轻量级容器来帮助该类测试。

在测试框架中,开发者能按步骤地加载Seam容器,然后运行测试。

9. 卓越的工具支持
对于一个聚焦于开发者生产力的应用框架,开发工具的支持至关重要。

Seam发布了一个基于命令行的生成器,称作 SeamGen。

SeamGen类似于Ruby-On-Rails 中的生成器,它支持诸如从一个数据库生成完整CRUD应用的功能,聪明的开发者会通过诸如“编辑/保存/在浏览器重新载入”的步骤、有测试支持的特性,来改进web应用。

但更重要的是,SeamGen生成项目不依赖于主流的Java集成开发环境,如Eclipse 和NetBeans。

有了SeamGen,开发者可以随时入门。

10. 让我们开始编码吧
总而言之,Seam为JavaEE应用削减了开发费用,同时,增加了Java EE 5.0不具有的强大的新功能。

在下节(节选自本书第二章),我们将给您展示一些实际代码例子来阐述Seam如何工作的。

你能通过网站
/seam/下载到本书中所有的例子的源代码。

Seam Hello World
JBoss Seam是EJB3和JSF中间的粘合剂,这是Jboss Seam最基本的和最广泛的应用。

通过被Seam管理的组件,Seam允许这两个框架之间无缝(不是有意双关的)的集成。

它为整个web应用拓展了基于注解的EJB3 POJO编程模型。

在层与层之间,没有了必需的手动JNDI查找,没有了冗长的JSF支持bean的声明,没有了过多facade方法,没有了艰辛的对象传递,快哉!
继续在Seam中使用JavaEE模式
在传统的java EE应用中,一些设计模式,例如JNDI查找、XML声明组件、值对象、facade是被强制使用的。

Seam用基于注解的POJO消除了这些人为的需求。

但是,当Seam应用中真正需要它们的时候,仍然可以自由地使用这些模式。

编写一个Seam web应用概念上很简单。

你只需要编码出下列组件:
∙实体对象代表数据模型。

实体对象可能是JPA或者Hibernate中的POJO 对象。

它们自动地映射到关系数据库表。

∙SF web页面展示了用户界面。

页面通过表单捕获用户的输入,并且显示结果。

表单域与其数据显示数据库表,这些表被映射到实体bean或者实
体bean的集合上。

∙EJB3 会话bean或者注解过的Seam POJO可以作为JSF Web页面的UI事件处理器。

它们处理封装在实体bean中的用户输入,为下一步(或者页
面)生成显示的数据对象。

所有以上组件均由Seam自行管理,它们在运行时被自动注入到正确的页面或者对象。

例如,当用户单击按钮提交一个JSF表单,Seam就会自动解析表单域并构造一个实体bean。

然后,Seam将实体bean传入同样被Seam构造的事件处理器会话bean中来处理。

开发者不需要在代码中管理组件的生命周期和组件之间的相互关系。

依赖处理过程中,没有样板代码和XML文件。

本章中,我们使用hello world一例来明确展示Seam如何粘合一个web应用。

该例子工作如下:用户能在web表单中输入其名字来“问候”Seam。

一旦她提交了表单,应用则保存她的名字到一个关系数据库中,并且显示所有已经“问候”过Seam的用户。

该项目示例在该书下载的源代码中的HelloWorld文件夹中。

为了建立它,你必须安装Apache ANT 1.6版本以上 (/)。

进入HelloWorld目录,运行命令ant,则会生成build/jars/helloworld.ear 文件,可以直接拷贝该文件到Jboss AS实例的server/default/deploy目录下。

现在,启动JBoss AS并且打开网址http://localhost:8080/helloworld/。

为了运行本书中的例子,我们建议您使用JEMS GUI安装程序安装一个与Seam
兼容的JBoss AS。

您可以从
/portal/jemsinstaller/downloads下载JEMS安装程序。

如果您需要更多安装JBoss AS和应用部署帮助,请参见附录A,“安装和部署JBoss AS”
欢迎使用示例作为模板,快速开始你自己Seam项目(参见附录B “使用应用示例作为模板”)。

或者,你能使用命令行工具Seam Gen (参见第四章“快速应用开发工具”)自动生成项目模板,包括所有的配置文件。

本章中,我将花少量的时间来阐释源代码项目中的目录结构。

相反,我们将集中讨论代码和配置,这也是开发者建立一个Seam 应用必需的。

如此,我们就能将知识应用到任何一个项目结构,而不需要受模板的限制。

源代码目录
一个Seam应用由java类和XML或文本配置文件组成。

本书的项目例子中,java 源代码文件在src目录中,网页在view 目录中,所有的配置文件都在resources 目录中。

更多信息请看附件B,使用应用示例作为模板。

1. 创建一个数据模型
Helloworld应用中的数据模型仅仅是一个有name和id属性的person 类。

注解@Entity告诉容器映射该类到一个关系数据库表,每个属性对应表中一个字段,每个person实例相当于表中的一条记录。

因为Seam采用非常规的配置方式,容器为表名和字段中仅仅使用类名和属性名。

属性id上的@Id和@GeneratedValue 注解暗示id字段是主键,它的值是应用服务器为每个保存到数据库的peron对象自动生成。

@Entity
@Name("person")
public class Person implements Serializable {
private long id;
private String name;
@Id @GeneratedValue
public long getId() { return id;}
public void setId(long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { = name;}
}
Person类中最重要的注解是@Name,它为这个将要注册于Seam中的Person bean 指定了名称。

在其他Seam组件中(例如,页面和会话bean)中,开发者能指直接使用“person”来引用被管理的Person bean。

2. 将数据模型映射到web表单
在JSF页面中,我们使用Person bean来支持表单输入文本域。

#{}符号指代名为“person”的Seam组件的name属性,名为“person”的Seam组件是Person实体bean的一个实例。

<h:form>
Please enter your name:<br/>
<h:inputText value="#{}" size="15"/><br/>
<h:commandButton type="submit" value="Say Hello"
action="#{manager.sayHello}"/>
</h:form>
通过以下的实体表单,JSF页面显示了数据库中所有已经向Seam说“hello”的用户。

用户名单列表存储在一个名为“fans”的Seam组件中,它是一个List 对象。

JSF dataTable通过遍历列表,每一行显示一个Person对象。

Fan标记是fans 列表的迭代子。

<h:dataTable value="#{fans}" var="fan">
<h:column>
<h:outputText value="#{}"/>
</h:column>
</h:dataTable>
图2.1显示了Hello World网页
当用户点击“Say Hello”按钮提交表单,Seam用输入数据构造了该person组件。

然后它调用了名为“manager”的Seam 组件的sayhello()的方法(像这样,#{manager.sayHello}是表单提交按钮的UI事件处理器),这就在数据库中保存了person对象并且刷新了fans列表。

名为manager的组件是一个EJB3的会话bean, 我们将在下节讨论该话题。

2. 处理web事件
Seam 中的名为manager的组件是会话bean ManagerAction,正如该类中@Name 注解指定的。

ManagerAction类有person和fans两个属性,这两个属性被@In 和@Out所注解。

@Stateless
@Name("manager")
public class ManagerAction implements Manager {
@In @Out
private Person person;
@Out
private List <Person> fans;
注解@In和@Out在Seam编程模型中处于核心。

因此,让我们看看到底它们在这里是做什么的。

注解@In告诉Seam,在此会话bean中,执行任何一个方法之前,Seam就会把由JSF表单构造的名为person组件赋给该person字段(通过依赖注入)。

开发者
能为@In中的注入的组件指定一个任意的名称,但是如果没有指定,如这里所示,Seam会将同类型以及同名称的组件注入到该字段中。

注解@Out告诉Seam,在执行任何方法后,Seam会将属性fans值和属性person的值都赋给被Seam管理的同名的组件。

在Seam中,我们将这个操作称作“依赖抛出”。

以此,在ManagerAction.sayHello()方法中,我们仅仅需要更新属性fans和属性person 的值,它们会自动显示在页面上。

什么是双向映射
在Seam 文件中,有时你就会看到术语“双向映射”。

它指的是被Seam管理的组件和Seam管理上下之间的注入和抛出。

因为person属性已经通过注入持有了表单数据,sayHello()方法仅仅是通过JPA EntityManager将它保存到数据库中,JPA EntityManager也是通过
@PersistenceContext注入的。

当方法返回之后,它便更新了fans和person对象并且把这两个对象抛出。

方法sayHello()一般会返回null,预示着在调用之后,更新的数据模型将在当前的JSF页面显示。

@PersistenceContext
private EntityManager em;
public String sayHello () {
em.persist (person);
person = new Person ();
fans = em.createQuery("select p from Person p")
.getResultList();
return null;
}
除了一些细节,我们基本完成了。

可能你已经注意到,ManagerAction bean类实现了Manager接口。

为了符合EJB3会话bean 规范,我需要一个能列出bean 中所有业务方法的方法。

下面是接口Manager代码,幸运的是,用任何高级IDE 工具都能轻松地自动生成这个接口。

@Local
public interface Manager {
public String sayHello ();
}
这就是在Hello World例子中需要的所有代码。

后面两章小节将涵盖Seam应用的其他方法和配置。

如果开发者为了自己的小型数据库应用想立即编码和定制helloworld项目,那么现在就可以跳过本章的剩余部分。

4. 更易于理解的seam编程模型
现在我们已经大致了解了Hello World的应用。

但是我们还有一些重要的话题继续,例如其他折中途径以及前面代码没有涉及到重要特性,我们将在本节讨论这些话题。

它们能帮助开发者对seam更深刻的理解,但是如果你没有耐心,可以直接跳过本节,需要的时再来阅读。

4.1 Seam POJO组件
上例中,我们用一个EJB3会话bean实现了应用逻辑,但是我们并不局限于EJB3组件。

事实上,Seam中任何一个有@Name注解的POJO都能被转化为一个可管理的组件。

例如,我们能将ManagerAction转化为一个 POJO,而不是一个EJB3 session bean。

@Name("manager")
public class ManagerAction {
@In (create=true)
private EntityManager em;
... ...
}
使用POJO取代EJB3 bean有正反两方面意见,使用POJO编程时很简单,因为它们不需要EJB3特有的注解和接口(参见上文)。

如果你的所有业务组件都是Seam POJO, 那么你就能不依赖EJB3应用服务器,运行你的Seam 应用(参见23章,没有EJB3的Seam)。

但是,POJO比EJB3的功能少,因为POJO不能获得EJB3容器服务。

在不依赖EJB3的Seam 中丧失的EJB3服务就包括以下几点:
∙@PersistenceContext注入在POJO中不在管用。

为了在一个Seam POJO 中得到EntityManager,开发者不得不在Seam配种文件中初始化
EntityManager,然后使用Seam注解@In将它注入到POJO中。

∙POJOs中将不在支持方法级别事务声明(declarative method-level transaction)。

相反,你可以配置Seam来划分事务,可以从收到web
请求开始直到响应页面产生结束。

∙Seam POJO不是消息驱动组件。

∙不支持注解为@Asynchronous的方法。

∙不支持容器安全管理。

∙没有事务或者组件级别的持久上下文。

Seam POJO中的所有的持久上下文都是经过拓展的(更多细节请参见7.1 “默认的对话作用域”)。

∙没有集成容器管理的体系结构(例如,JMX控制台服务)。

∙Seam POJO方法中没有Java RMI。

∙Seam POJO不能是注解为@WebService组件。

∙没有JCA集成。

所以当在EJB3容器中进行部署时,为什么每个人都想使用POJO组件?答案就是,POJO组件对于纯“业务逻辑”组件非常有益。

POJO为其他组件代理了数据访问、消息传递和其他基本功能。

例如,我们能使用POJO组件操纵Seam数据访问对象,这对“业务逻辑”POJO是非常有用的,因为它们可以在需要的时候,在其他框架中被重用。

但是总的来说,它们的应用要比EJB3组件少,特别是在中小型应用中。

所以,本书的大多数例子我们都使用EJB3组件。

4.2 易于测试
我们已经在第一章中提到,Seam为了不依赖容器的方便的测试,进行了重新设计。

在helloworld项目中,我们在测试文件夹中包括了单元测试和集成测试这两个测试用例。

在纯Java SE环境下,Seam 测试体系模拟了数据库、JSF、Seam 上下文以及其他应用服务器服务,只要运行ant test命令就能运行所有的测试。

4.3 基于Getter和Setter的双向映射
在Hello World一例中,我们已经展示了通过成员变量对Seam组件进行的双向映射,你也能通过Getter和Setter方法对组件进行双向映射。

例如,以下代码就工作的很好。

private Person person;
private List <Person> fans;
@In
public void setPerson (Person person) {
this.person = person;
}
@Out
public Person getPerson () {
return person;
}
@Out
public List <Person> getFans () {
return fans;
}
虽然以上的getter和setter方法看似轻微,利用getter和setter方法的双向映射真正的价值在于能其加入定制逻辑来操纵双向映射的过程。

例如,你可以验证被注入的对象或者快速地从数据库重新得到被抛出的对象。

4.4避免过度的双向映射
在Hello World一例中 ,通过将数据组件作为业务组件的属性,可以轻易的减少或者消除双向映射。

在JSF页面中,通过这种方式,开发者只需要引用业务组件,而不需要在业务组件和数据组件之间的双向映射。

例如,开发者可以修改ManagerAction类为以下所述。

依赖双向映射是一个非常实用的设计模式。

但是,正如其他设计模式,过度使用就会有害。

过度的依赖双向映射让代码变得难以阅读,因为开发者必须理解每个注入的组件出自何处。

过度的依赖双向映射也能增加性能消耗,因为双向映射是在运行时进行。

@Stateless
@Name("manager")
public class ManagerAction implements Manager {
private Person person;
public Person getPerson () {return person;}
public void setPerson (Person person) {
this.person = person;
}
private List <Person> fans;
public List<Person> getFans () {return fans;}
... ...
}
接下来,我们在页面上引用的属性如下:
<h:form>
Please enter your name:<br/>
<h:inputText value="#{}"/>
<br/>
<h:commandButton type="submit" value="Say Hello"
action="#{manager.sayHello}"/>
</h:form>
... ...
<h:dataTable value="#{manager.fans}" var="fan">
<h:column>
<h:outputText value="#{}"/>
</h:column>
</h:dataTable>。

相关文档
最新文档