追
--业余delphi、java爱好者
登录
注册
全站
当前博客
空间
博客
好友
相册
留言
迈克
ID:bq_cui
共
15771
次访问,排名
7246
好友
0
人,关注者
2
人
玩,自由,旅游,
bq_cui的文章
原创 45 篇
翻译 9 篇
转载 5 篇
评论 19 篇
最近评论
sjxun:
很不错..呵呵..谢谢!
bq_cui:
根据zqq7231的说法,FCKedicator这个包里面应该有commons-fileupload.jar,可能用这个包里面的commons-fileupload.jar可以。我没有试。
fftaks:
wow power leveling
haoyangguang:
解决了说一下了谢谢
MAGIC_ST:
你好,我现在也碰到了这个问题,请问你的是否解决了,还有"结果把原来的commons-fileupload.jar换成从FCKedicator上面拿下来的就可"这一句是什么意思,我在
FCKedicator里没有看到commons-fileupload.jar
,如果你解决了可以说说是怎么解决的吗??谢谢
文章分类
delphi
(RSS)
jise
(RSS)
mysql
(RSS)
seam
(RSS)
其他
(RSS)
数据库
(RSS)
休闲
(RSS)
演示
(RSS)
收藏
delphi
seam
错误解决
相册
ise使用指南之一-pic1
插入中文富文本
java
jboss
LUCENE
寿光华泰钢架大棚有限公司
昨夜西风凋碧树的精神家园
李青阳的博客
存档
2008年08月(1)
2008年07月(2)
2008年06月(5)
2008年05月(1)
2008年04月(4)
2008年01月(1)
2007年10月(2)
2007年09月(8)
2007年08月(5)
2007年07月(3)
2007年06月(1)
2007年05月(4)
2007年04月(8)
2007年03月(14)
软件项目交易
订阅我的博客
Chapter 11. Seam 应用程序框架
收藏
新一篇: Chapter 4. 设置 Seam 组件
|
旧一篇: 下载我完成的tinyMCE(第二次修改)
(今天是2007年国庆日,能在今天加班搞农业普查数据处理,并抽闲翻译这样一篇seam文章,真的是特别特别有意义噢。
)
通过写带标注的普通java类,seam使创建应用变得非常容易。这样的类不需要扩展任何特殊的接口或超类。通过提供一系列内置组件,我们可以进一步简化一些通用的编程工作。对这些内置组件的使用是通过设置xomponents.xml(适用于简单情况)或其他的设置。
在一个应用中,如果需要使用Hibernate 或 JPA对数据库进行基本操作,Seam 应用程序框架可以减少编码数量。
需要强调的是,这个框架极其简单,仅仅少量的简单易懂的、易于扩展的类。“魔法”就在seam本身-即使你创建seam应用时没有使用这个框架,你也在使用同样的魔法。
11.1. 前言
Seam 应用程序框架提供的组件可以用以下两种方式之一使用:
第一种,在components.xml安装、设置组件实例,就像我们使用其他类型seam组件。例如,以下components.
xml代码片段安装一个组件,可以对Person entity进行基本操作:
<
framework:entity-home
name
="personHome"
entity-class
="eg.Person"
entity-manager
="#{personDatabase}"
>
<
framework:id
>
#{param.personId}
</
framework:id
>
</
framework:entity-home
>
如果这样看起来太像“在xml中编程”,亦可以这样使用扩展方式:
@Stateful
@Name(
"
personHome
"
)
public
class
PersonHome
extends
EntityHome
<
Person
>
implements
LocalPersonHome
...
{
@RequestParameter String personId;
@In EntityManager personDatabase;
public
Object getId()
...
{
return
personId; }
public
EntityManager getEntityManager()
...
{
return
personDatabase; }
}
第二种方式有较大优势:可以方便地加入额外函数,并覆盖内置函数(为便于扩展和定制,框架类已被仔细设计)。
第二个优势是,你的类可以是EJB stateful sessin beans(并非必须如此,只要你愿意,也可以是plain JavaBean components)。
截至目前,seam应用程序框架提供了四种内置组件:EntityHome 、HibernateEntityHome
for CRUD、EntityQuery 、 HibernateEntityQuery for queries。
Home 与 Query组件可以用在这些工作期中:session, event 或conversation。使用何种工作期取决于你的应用程序的状态模型。
seam应用程序框架仅适用Seam-managed persistence contexts。默认情况,组件将查找名称为entityManager的persistence context。
11.2. Home objects
一个Home object提供了对一个特定entity class的持久化操作(persistence operations)。假设有这样一个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 object提供了以下操作:persist(), remove(), update() and 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 entries。是的,这就是所需的全部代码!现在,如果我们想要显示、更新、删除数据库中的Person 记录,则需要把记录的id传给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.
persist
}"
/>
<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);
}
}
The Seam Application Framework
当然,Country 可能是一个由其他Home object管理的对象,例如,CountryHome。为了增加更多复杂操作(例如关联管理,等等),我们可以对PersonHome增加方法(methods)。
@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();
}
}
如果一个操作成功完成,Home对象自动显示faces messages。为定制这些信息,我们再一次通过设置的方式:
<
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>,不过我想把这些任务留给你。
11.3. Query objects
如果需要数据库中
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
>
或者,当person记录通过
PersonHome
保存、更新、删除后,为马上刷新查询:
<
event
type
="org.jboss.seam.afterTransactionSuccess.Person"
>
<
action
execute
="#{people.refresh}"
/>
</
event
>
以上例子显示了通过设置的方式达到复用。不过,对Query 对象来说,通过扩展的方式达到复用也是同样可以的。
11.4. Controller objects
在Seam应用框架中完全可选的部分是Controller 类和它的子类Entity-Controller HibernateEntityController 和 BusinessProcessController。它们提供了操作常用的内置组件及其方式的捷径。它们可以节省击键次数(自动添加字符),对新手学习seam的内在功能有很大的推动作用。
例如,Seam registration例子中的RegisterAction看上去像这样:
@Stateless
@Name(
"
register
"
)