本站首页    管理页面    写新日志    退出

公告

You are all my reasons! 

桃李花林又一在

淫荡一日同风起,风骚直上九万里

仙子凌波微步罗衫飘忽十步一回头

我的最爱:网游,程序,文学

QQ:89636669


我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:一维空间
日志总数:163
评论数量:248
留言数量:33
访问次数:650133
建立时间:2007年10月24日




 [JAVA]Seam 例子 Hello World【转】

dskongenius 发表于 2008/11/28 22:59:23

转自http://hi.baidu.com/yanru8402/blog/item/a3b3ad543f5b4b1a3a293593.html     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版本以上 (http://ant.apache.org/)。进入HelloWorld目录,运行命令ant,则会生成build/jars/helloworld.ear文件,可以直接拷贝该文件到Jboss AS实例的server/default/deploy目录下。现在,启动JBoss AS并且打开网址http://localhost:8080/helloworld/。 为了运行本书中的例子,我们建议您使用JEMS GUI安装程序安装一个与Seam兼容的JBoss AS。您可以从http://labs.jboss.com/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) {this.name = name;}} Person类中最重要的注解是@Name,它为这个将要注册于Seam中的Person bean指定了名称。在其他Seam组件中(例如,页面和会话bean)中,开发者能指直接使用“person”来引用被管理的Person bean。 2. 将数据模型映射到web表单 在JSF页面中,我们使用Person bean来支持表单输入文本域。#{person.name}符号指代名为“person”的Seam组件的name属性,名为“person”的Seam组件是Person实体bean的一个实例。 <h:form>Please enter your name:<br/><h:inputText value="#{person.name}" size="15"/><br/><h:commandButton type="submit" value="Say Hello"                 action="#{manager.sayHello}"/></h:form> 通过以下的实体表单,JSF页面显示了数据库中所有已经向Seam说“hello”的用户。用户名单列表存储在一个名为“fans”的Seam组件中,它是一个List 对象。JSFdataTable通过遍历列表,每一行显示一个Person对象。Fan标记是fans列表的迭代子。 <h:dataTable value="#{fans}" var="fan">  <h:column>    <h:outputText value="#{fan.name}"/>  </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工具都能轻松地自动生成这个接口。 @Localpublic 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;@Inpublic void setPerson (Person person) {  this.person = person;}@Outpublic Person getPerson () {  return person;}@Outpublic 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="#{manager.person.name}"/><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="#{fan.name}"/>  </h:column></h:dataTable> 最后,具有了依赖管理的Seam是多用的。通常用数据访问业务组件封装数据是一项好的实践,特别是针对有状态业务组件。 4.5 JSF中的页面导航 本例中,只有一个页面。每次点击按钮后,JSF页面会重新显示更新过的数据模型。显然,大多数web应用多于一个页面。在JSF中,一个用户界面事件处理器能通过返回导航规则名称,决定下一步该显示哪个页面。例如,开发者可以在navigation.xml中定义以下导航规则。 <navigation-case>  <from-outcome>anotherPage</from-outcome>  <to-view-id>/anotherPage.jsp</to-view-id></navigation-case> 之后,如果sayHello()方法返回一个名为“another page”的字符串,JSF下一步就该展示anotherPage.jsp。UI事件处理器决定了接下来要显示哪个页面,从而为我们带来了有步骤的控制。 4.6 通过EntityManager访问数据库 JPA(Java Persistence API)EntityManager管理着关系数据库表与实体bean 之间的映射。EntityManager 在运行时由应用服务器创建。你能使用注解@PersistenceContext,注入一个EntityManager的实例。
阅读全文(4551) | 回复(0) | 编辑 | 精华

 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.047 second(s), page refreshed 144753458 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号