- 浏览: 77275 次
- 性别:
- 来自: 重庆
最新评论
-
禀圣含华:
怎么弄空格呢?___________然后我固定这些空格,怎么弄 ...
第18章. iText PDF 生成 -
super0555:
managed
第13章 Seam 应用程序框架 -
Javakeith:
代码呢?共享下代码呗!
第18章. iText PDF 生成 -
tonyshen277:
同感啊。还在做Win32下的开发,楼主所说的一个都不能少啊。
转自baidu wqqq 给软件开发初学者 -
kdboy:
的确,把人放在宇宙中去看,从上帝的眼中去看,人的确是非常渺小, ...
人生是什么
第13章 Seam 应用程序框架
Seam真正地使通过写带注释的简单Java类来创建应用程序变得容易,它不需要继承任何特别的接口或超类。但是,我们能更进一步简化一些通用的编程任务,通过提供预先构建的组件集,它能通过配置components.xml(为非常简单的情况)或继承被重用。
当在一个网页应用程序中,使用Hibernate 或 JPA进行基本的数据访问时,Seam应用程序框架能减少你需要写的大量代码。
我们应该强调框架是非常简单的,只是少数简单类,容易理解和继承。“魔术”是在Seam它自身——即使没有使用这个框架,当创建任何Seam应用程序时,你使用了同样的魔术。
13.1.介绍
由Seam 应用程序框架提供的组件可以被使用在两种不同的方法中。第一种方法是在components.xml中安装并配置一个组件实例,就如我们用其他的种类的内建Seam组件已做的那样。例如,来自components.xml文件的下面片断安装了一个组件,它能对一个Person实体执行基本的CRUD(弄脏)操作:
<framework:entity-home name="personHome"
entity-class="eg.Person"
entity-manager="#{personDatabase}">
<framework:id>#{param.personId}</framework:id>
</framework:entity-home>
如果你觉得看起来太象“在XML中编程”,你可以使用继承来代替:
@Name("personHome")
public class PersonHome extends EntityHome<Person> {
@In EntityManager personDatabase;
public EntityManager getEntityManager() {
return personDatabase;
}
}
第二个方法有一个巨大的优点:你能容易增加额外的功能,覆盖内建功能(为了扩展和自定义,框架类被小心设计)。
第二个优点是你的类可以是EJB有状态会话bean,如果你喜欢。(它们不必是,它们可以是你喜爱的简单JavaBean组件)如果你使用JBoss AS,你需要4.2.2.GA或以后的版本:
@Stateful
@Name("personHome")
public class PersonHome extends EntityHome<Person> implements LocalPersonHome {
}
你也可以使你的类成为无状态会话bean。在这个情形中,你必须使用注入来提供持久化上下文,即便它被称为entityManager:
@Stateless
@Name("personHome")
public class PersonHome extends EntityHome<Person> implements LocalPersonHome {
@In EntityManager entityManager;
public EntityManager getPersistenceContext() {
entityManager;
}
}
在这个时候,Seam应用程序框架提供了四个主要的内建组件:用于CRUD(弄脏)操作的EntityHome 和HibernateEntityHome,相应的用于查询操作的EntityQuery 和HibernateEntityQuery。
编写Home和 Query组件的目的在于它们可能与会话、事件或对话作用域一起运行。你使用那个作用域,取决于你希望在你的应用程序中使用的状态模型。
Seam应用程序框架只与受管理的Seam持久化上下文一起工作。在缺省时,组件会查找名为entityManager的持久化上下文。
13.2. Home 对象
一个Home对象为一个特定的实体类提供持久化操作,假设我们有一个可信赖 Person 类:
@Entity
public class Person {
@Id private Long id;
private String firstName;
private String lastName;
private Country nationality;
//getters and setters...
}
我们能通过配置定义一个 personHome 组件:
<framework:entity-home name="personHome" entity-class="eg.Person" />
或者通过继承 :
@Name("personHome")
public class PersonHome extends EntityHome<Person> {}
一个Home对象提供了如下的操作:persist()、remove()、update() 和 getInstance()。 在你能够调用 remove() 或 update() 操作之前,你必须首先使用 setId() 方法定义你感兴趣的对象的标识符。
我们能直接从一个JSF页面使用一个Home对象,例如:
<h1>Create Person</h1>
<h:form>
<div>First name: <h:inputText value="#{personHome.instance.firstName}"/></div>
<div>Last name: <h:inputText value="#{personHome.instance.lastName}"/></div>
<div>
<h:commandButton value="Create Person" action="#{personHome.persist}"/>
</div>
</h:form>
通常,能够仅作为person引用Person是更好得多,所以,通过增加一行到components.xml文件,我们让使这个成为可能:
<factory name="person"
value="#{personHome.instance}"/>
<framework:entity-home name="personHome"
entity-class="eg.Person" />
(如果我们使用配置。)或者通过增加一个@Factory方法给PersonHome:
@Name("personHome")
public class PersonHome extends EntityHome<Person> {
@Factory("person")
public Person initPerson() { return getInstance(); }
}
(如果我们使用继承。)这个变化简化了我们的JSF页面,如下面:
<h1>Create Person</h1>
<h:form>
<div>First name: <h:inputText value="#{person.firstName}"/></div>
<div>Last name: <h:inputText value="#{person.lastName}"/></div>
<div>
<h:commandButton value="Create Person" action="#{personHome.persist}"/>
</div>
</h:form>
好的,这让我们创建了新的Person入口。是的,那就是必要的所有代码!现在,如果我们想能够显示、更新和删除数据库中预先存在的Person条目,我们需要能够传条目标识给PersonHome。页面参数是做这些的一个主要的方法:
<pages>
<page view-id="/editPerson.jsp">
<param name="personId" value="#{personHome.id}"/>
</page>
</pages>
现在我们能对JSF页面增加额外的操作:
<h1>
<h:outputText rendered="#{!personHome.managed}" value="Create Person"/>
<h:outputText rendered="#{personHome.managed}" value="Edit Person"/>
</h1>
<h:form>
<div>First name: <h:inputText value="#{person.firstName}"/></div>
<div>Last name: <h:inputText value="#{person.lastName}"/></div>
<div>
<h:commandButton value="Create Person" action="#{personHome.persist}"
rendered="#{!personHome.managed}"/>
<h:commandButton value="Update Person" action="#{personHome.update}"
rendered="#{personHome.managed}"/>
<h:commandButton value="Delete Person" action="#{personHome.remove}"
rendered="#{personHome.managed}"/>
</div>
</h:form>
当我们不用请求参数链接到页面,页面将以"Create Person"页面显示。当我们为personId请求参数提供了一个值时,它会是一个"Edit Person"页面。
假如我们需要用他们国家初始化来创建Person条目。通过配置我们能容易做那事:
<factory name="person"
value="#{personHome.instance}"/>
<framework:entity-home name="personHome"
entity-class="eg.Person"
new-instance="#{newPerson}"/>
<component name="newPerson"
class="eg.Person">
<property name="nationality">#{country}</property>
</component>
或者用继承:
@Name("personHome")
public class PersonHome extends EntityHome<Person> {
@In Country country;
@Factory("person")
public Person initPerson() { return getInstance(); }
protected Person createInstance() {
return new Person(country);
}
}
当然,Country可能是被另外的Home对象管理的对象,如CountryHome。
为了增加更多复杂的操作(联合管理,等等),我们能仅增加方法给PersonHome。
@Name("personHome")
public class PersonHome extends EntityHome<Person> {
@In Country country;
@Factory("person")
public Person initPerson() { return getInstance(); }
protected Person createInstance() {
return new Person(country);
}
public void migrate()
{
getInstance().setCountry(country);
update();
}
}
当一个事务成功时(一个persist()、update() 或remove()调用成功),Home对象触发一个org.jboss.seam.afterTransactionSuccess事件。通过遵守这个事件,当底层的实体被改变时,我们能刷新我们的查询。当一个特殊的实体被持久化、更新或删除时,如果我们只想刷新某些查询,我们能遵守org.jboss.seam.afterTransactionSuccess.<name>事件(这里的<name>是实例的名字)。
<factory name="person"
value="#{personHome.instance}"/>
<framework:entity-home name="personHome"
entity-class="eg.Person"
new-instance="#{newPerson}">
<framework:created-message>New person #{person.firstName} #{person.lastName} created</framework:created-message>
<framework:deleted-message>Person #{person.firstName} #{person.lastName} deleted</framework:deleted-message>
<framework:updated-message>Person #{person.firstName} #{person.lastName} updated</
framework:updated-message>
</framework:entity-home>
<component name="newPerson"
class="eg.Person">
<property name="nationality">#{country}</property>
</component>
或者用继承:
@Name("personHome")
public class PersonHome extends EntityHome<Person> {
@In Country country;
@Factory("person")
public Person initPerson() { return getInstance(); }
protected Person createInstance() {
return new Person(country);
}
protected String getCreatedMessage() { return "New person #{person.firstName}
#{person.lastName} created"; }
protected String getUpdatedMessage() { return "Person #{person.firstName}
#{person.lastName} updated"; }
protected String getDeletedMessage() { return "Person #{person.firstName}
#{person.lastName} deleted"; }
}
但是指定消息的最好的方法是放它们在Seam所知的一个资源“束”中(缺省时,“束”被命名为messages)
Person_created=New person #{person.firstName} #{person.lastName} created
Person_deleted=Person #{person.firstName} #{person.lastName} deleted
Person_updated=Person #{person.firstName} #{person.lastName} updated
这使国际化成为可能,并且保持了你的代码和配置的描述关系的整洁
最后一步是给页面增加校验功能,使用<s:validateAll>和<s:decorate>,但是,我留给你去解决。
13.3. Query对象
如果我们需要在数据库中的所有Person实例的一个列表,我们可以使用一个Query对象,例如:
<framework:entity-query name="people" ejbql="select p from Person p"/>
我们可以从一个JSF页面使用它:
<h1>List of people</h1>
<h:dataTable value="#{people.resultList}" var="person">
<h:column>
<s:link view="/editPerson.jsp" value="#{person.firstName} #{person.lastName}">
<f:param name="personId" value="#{person.id}"/>
</s:link>
</h:column>
</h:dataTable>
我们或许需要支持分页:
<framework:entity-query name="people"
ejbql="select p from Person p"
order="lastName"
max-results="20"/>
我们会使用一个页面参数来决定显示页面:
<pages>
<page view-id="/searchPerson.jsp">
<param name="firstResult" value="#{people.firstResult}"/>
</page>
</pages>
用于一个分页控制的JSF代码是有一点冗余,但是是可管理的:
<h1>Search for people</h1>
<h:dataTable value="#{people.resultList}" var="person">
<h:column>
<s:link view="/editPerson.jsp" value="#{person.firstName} #{person.lastName}">
<f:param name="personId" value="#{person.id}"/>
</s:link>
</h:column>
</h:dataTable>
<s:link view="/search.xhtml" rendered="#{people.previousExists}" value="First Page">
<f:param name="firstResult" value="0"/>
</s:link>
<s:link view="/search.xhtml" rendered="#{people.previousExists}" value="Previous Page">
<f:param name="firstResult" value="#{people.previousFirstResult}"/>
</s:link>
<s:link view="/search.xhtml" rendered="#{people.nextExists}" value="Next Page">
<f:param name="firstResult" value="#{people.nextFirstResult}"/>
</s:link>
<s:link view="/search.xhtml" rendered="#{people.nextExists}" value="Last Page">
<f:param name="firstResult" value="#{people.lastFirstResult}"/>
</s:link>
真实的搜索屏幕让用户输入一串搜索标准选项来缩小返回的结果列表。Query对象让你指定可选的“约束”选项来支持这个重要的用例:
<component name="examplePerson" class="Person"/>
<framework:entity-query name="people"
ejbql="select p from Person p"
order="lastName"
max-results="20">
<framework:restrictions>
<value>lower(firstName) like lower( concat(#{examplePerson.firstName},'%') )</value>
<value>lower(lastName) like lower( concat(#{examplePerson.lastName},'%') )</value>
</framework:restrictions>
</framework:entity-query>
注意"example"对象的使用:
<h1>Search for people</h1>
<h:form>
<div>First name: <h:inputText value="#{examplePerson.firstName}"/></div>
<div>Last name: <h:inputText value="#{examplePerson.lastName}"/></div>
<div><h:commandButton value="Search" action="/search.jsp"/></div>
</h:form>
<h:dataTable value="#{people.resultList}" var="person">
<h:column>
<s:link view="/editPerson.jsp" value="#{person.firstName} #{person.lastName}">
<f:param name="personId" value="#{person.id}"/>
</s:link>
</h:column>
</h:dataTable>
在底层实体发生改变时,我们遵守 org.jboss.seam.afterTransactionSuccess
事件来刷新查询:
<event type="org.jboss.seam.afterTransactionSuccess">
<action execute="#{people.refresh}" />
</event>
或者,当pearson实体通过 PersonHome持久化、更新或删除时,只刷新查询:
<event type="org.jboss.seam.afterTransactionSuccess.Person">
<action execute="#{people.refresh}" />
</event>
不幸地,Query 对象不能很好地支持join fetch 查询——用这些查询的分页使用不被推荐,并且你不得不实现你自己的计算结果总数的方法(通过覆盖getCountEjbql())。
在这部分的例子通过配置已完全展示了重用性。然而,对Query对象通过继承的重用同样可能的。
13.4. Controller对象
Seam应用程序框架的一个完全可选部分是类Controller和它的子类EntityController,HibernateEntityController 和 BusinessProcessController。这些类无非为访问常用内置组件和内建组件的方法提供一些方便的方法。它们帮助节省一些键盘输入(字符能增加!),并为探索在Seam内置丰富功能的初学者提供一个很好的跳板。
例如,这是来自Seam注册实例中的 RegisterAction,看起来就象:
@Stateless
@Name("register")
public class RegisterAction extends EntityController implements Register
{
@In private User user;
public String register()
{
List existing = createQuery("select u.username from User u where u.username=:username")
.setParameter("username", user.getUsername())
.getResultList();
if ( existing.size()==0 )
{
persist(user);
info("Registered new user #{user.username}");
return "/registered.jspx";
}
else
{
addFacesMessage("User #{user.username} already exists");
return null;
}
}
}
与你所看到的一样,这不是什么极其重大的改进……
发表评论
-
第31章. Seam内建组件
2009-05-28 11:51 1389第31章. Seam内建组件 本章描述Seam内建组件 ... -
第30章. Seam注释
2009-05-26 20:21 1500第30章. Seam注释 在你编写一个Seam应用程 ... -
第31章. Seam内建组件
2009-05-26 20:21 1338第31章. Seam内建组件 本章描述Seam内建组件 ... -
第29章. 配置Seam和打包Seam应用程序
2009-05-26 20:19 1479第29章. 配置Seam和打包Seam应用程序 配置 ... -
第28章. Hibernate搜索
2009-05-26 20:17 148828.1. 介绍 如Apache Lucen ... -
第27章. Spring框架集成
2009-05-26 20:16 1331第27章. Spring框架集成 Spring集成 ... -
第26章. Seam和Google网页工具
2009-05-26 20:15 1157第26章. Seam和Google网页工具 ... -
第25章. 远程
2009-05-26 20:15 1214第25章. 远程 Seam 提供了一个从网页远程访 ... -
第24章. Web服务
2009-05-26 20:15 1584第24章. Web服务 Seam 集成了JBossWS, ... -
第23章. 缓存
2009-05-26 20:14 1346第23章. 缓存 在 ... -
第22章. 异步和消息
2009-05-26 20:12 2057第22章. 异步和消息 Seam 使异步执行来自网页请 ... -
第21章. Email
2009-05-26 20:11 1262现在Seam包含一个用于模板和发送邮件的可选组件。 Emai ... -
第 20章. RSS支持
2009-05-26 20:10 782第 20章. RSS支持 20.1. 安装 20.2. ... -
第19章. 微软的Excel 电子表格应用程序支持
2009-05-26 20:07 1783第19章. 微软的Excel 电子表格应用程序支持 S ... -
第18章. iText PDF 生成
2009-05-26 20:01 6379第18章. iText PDF 生成 18.1. 使用PDF ... -
第17章. Seam文本
2009-05-26 19:59 997第17章. Seam文本 面向协作站点需要一种更有友好的 ... -
第16章. 国际化、本地化和主题
2009-05-26 19:57 1332第16章. 国际化、本地化和主题 Seam使构建国际化应用程 ... -
第15章 安全(2)
2009-05-26 19:56 892第15章 安全(2) 15.5. 错误消息 安全 ... -
第15章 安全(1)
2009-05-26 19:53 93815.1. 概述 Seam安全API为你基于Seam的 ... -
第14章 Seam 和 JBoss 规则
2009-05-26 19:50 1372第14章 Seam 和 JBoss 规则 Seam使从 ...
相关推荐
Seam2.10安全API为你使用Seam开发的应用程序提供了大量与安全认证相关的特性,包含了以下几块: • 安全验证 - 一个可扩展的、基于JAAS的安全验证层,允许用户to authenticate against any security provider • ...
Seam全称是Jboss Seam,是一个Java EE 5框架。它通过把JSF与EJB3.0组件合并在一起,以及利用JDK5.0的Annotation技术,从而为开发基于Web的企业应用程序提供一个最新的模式。
eam适应快速开发、简化框架的趋势,Seam给我的感觉像是一个异常简单的MVC框架
为 JSF 量身定做的应用程序框架,JavaServer Faces (JSF) 是用于 Java™ Web 应用程序的第一个标准化的用户界面框架。而 Seam 是一个扩展 JSF 的强大的应用程序框架。在这个由三部分组成的新系列中的第一篇文章中,...
Seam Security 中的验证特性是基于JAAS (Java Authentication and Authorization Service)开发的,它提供了用来进行用户身份认证的高度可配置的接口。然而,针对复杂多变的验证需求,Seam Security 提供了一套非常...
seam+richfaces环境框架的配置文件,经过我多次尝试才配置好的环境配置文件,很有用,适合刚接触这些技术的初学者,希望大家支持!
Seam全称是Jboss Seam,是一个Java EE 5框架。它通过把JSF与EJB3.0组件合并在一起,以及利用JDK5.0的Annotation技术,从而为开发基于Web的企业应用程序提供一个最新的模式。Seam可以让你把EJB组件直接绑定到JSF页面...
Seam 是一种业级 企 Java 的应规用程序框架。它的灵感源自下列原 : 只有一种“工具” Seam为 应 业务业业 义 种统 组 你的 用程序中所有的 定 了一 一的 件模型。 Seam组件可能是 态义 关关 态 有状 的,包含与几...
该资源介绍了seam 整合hibernate和jsf
很好的seam教程,较为详尽的参考资料。seam快速开发框架
JBOSS.SEAM.WEB应用开发 中文版 (美)MichaelYuan.
seam下一代web开发框架
1.6. 一个完整的Seam 应用程序:宾馆预订范例............................................................................................................ 45 1.6.1. 介绍......................................
seam包自带了一些例子,本文帮助你如何使用ant部署并执行seam的例子,省去了用jboss ide或者eclipse部署seam项目带来的麻烦
seam框架的相关知识总结,比较全面,希望有用
seam_carving代码实现 图像缩放
seam 中文文档 pdf 格式 JSF+EJB3.0快速开发框架Seam的中文版向导。。。
seam框架需要的所有jar包,支持seam ui组件
Seam in action的第14章,讲了jBPM在Seam中的应用
JBOSS_SEAM配置