SEAM学习(二)---messages示例

本文介绍了一个基于Seam框架实现的消息应用示例,包括实体Bean、Session接口及Bean的定义,展示了如何通过JSF页面展示消息列表并进行操作。
实体bean:message

//$Id: Message.java 902 2006-01-13 14:19:20Z theute $
package org.jboss.seam.example.messages;

import static org.jboss.seam.ScopeType.EVENT;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.validator.Length;
import org.hibernate.validator.NotNull;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;

@Entity
@Name("message")
@Scope(EVENT)
public class Message implements Serializable
{
private Long id;
private String title;
private String text;
private boolean read;
private Date datetime;

@Id @GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}

@NotNull @Length(max=100)
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}

@NotNull @Lob
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}

@NotNull
public boolean isRead() {
return read;
}
public void setRead(boolean read) {
this.read = read;
}

@NotNull
@Basic @Temporal(TemporalType.TIMESTAMP)
public Date getDatetime() {
return datetime;
}
public void setDatetime(Date datetime) {
this.datetime = datetime;
}

}

-------------------------------------------------------------------------------------------------------------------------

session 接口:

//$Id: MessageManager.java 1584 2006-05-23 05:30:24Z gavin $
package org.jboss.seam.example.messages;

import javax.ejb.Local;

@Local
public interface MessageManager
{
public void findMessages();
public void select();
public void delete();
public void destroy();
}

---------------------------------------------------------------------------------------------------------------------------------

session bean:

//$Id: MessageManagerBean.java 2711 2006-11-19 21:01:33Z gavin $
package org.jboss.seam.example.messages;

import static javax.persistence.PersistenceContextType.EXTENDED;
import static org.jboss.seam.ScopeType.SESSION;

import java.io.Serializable;
import java.util.List;

import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.datamodel.DataModel;
import org.jboss.seam.annotations.datamodel.DataModelSelection;

@Stateful
@Scope(SESSION)

//这是个会话作用域的Seam组件。它与用户登入会话相关联,

并且登入会话的所有请求共享同一个组件的实例。(在Seam的应用中,我们通常使用会话作用域的组件。)
@Name("messageManager")
public class MessageManagerBean implements Serializable, MessageManager
{

@DataModel
private List<Message> messageList;
//注解 @DataModel 暴露了 java.util.List 类型的属性给JSF页面来作为 javax.faces.model.DataModel 的实例。

这允许我们在JSF <h:dataTable>的每一行中能使用可点击列表。在此例中,DataModel 可在变量名为 messageList 的会话上下文中被使用。

@DataModelSelection //@DataModelSelection 注解告诉了Seam来注入 List 元素到相应的被点击链接。
@Out(required=false) //注解 @Out 直接暴露了被选中的值给页面。 这样一来,每次可点击列表一旦被选中,

Message 就被会注入给有状态Bean的属性,紧接着 向外注入(outjected)给变量名为 message 的事件上下文的属性。
private Message message;

@PersistenceContext(type=EXTENDED)

//EJB3的 扩展持久化上下文(extended persistence context)。只要Bean存在,查询中获取的消息就会保留在受管理的状态中。

这样一来,此后对有状态Bean的所有方法调用勿需显式调用 EntityManager 就可更新这些消息了。
private EntityManager em;

@Factory("messageList")

//当我们第一次浏览JSP页面时,messageList 上下文变量尚未被初始化,@Factory 注解告诉Seam来创建

MessageManagerBean 的实例并调用 findMessages() 方法来初始化上下文变量。

我们把 findMessages() 当作 messages 的 工厂方法。

public void findMessages()
{
messageList = em.createQuery("select msg from Message msg order by msg.datetime desc").getResultList();
}

public void select()
{
if (message!=null) message.setRead(true);

//select() 将选中的 Message 标为已读,并同时更新数据库。

}

public void delete()
{
if (message!=null)
{
messageList.remove(message);
em.remove(message);
message=null;
}

//delete() 动作监听器方法将选中的 Message 从数据库中删除。

}

@Remove @Destroy
public void destroy() {}

//对于每个有状态的会话Bean,Seam组件的所有方法中 必须 有一不带参数的方法被标为 @Remove @Destroy

以确保在Seam的上下文结束时删除有状态Bean,并同时清除所有服务器端的状态。

}

------------------------------------------------------------------------------------------------------------------

页面:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://jboss.com/products/seam/taglib" prefix="s" %>
<html>
<head>
<title>Messages</title>
</head>
<body>
<f:view>
<h2>Message List</h2>
<h:outputText value="No messages to display" rendered="#{messageList.rowCount==0}"/>
<h:dataTable var="msg" value="#{messageList}" rendered="#{messageList.rowCount>0}">
<h:column>
<f:facet name="header">
<h:outputText value="Read"/>
</f:facet>
<h:selectBooleanCheckbox value="#{msg.read}" disabled="true"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Title"/>
</f:facet>
<s:link value="#{msg.title}" action="#{messageManager.select}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Date/Time"/>
</f:facet>
<h:outputText value="#{msg.datetime}">
<s:convertDateTime type="both" dateStyle="medium" timeStyle="short"/>
</h:outputText>
</h:column>
<h:column>
<s:button value="Delete" action="#{messageManager.delete}"/>
</h:column>
</h:dataTable>
<h3><h:outputText value="#{message.title}"/></h3>
<div><h:outputText value="#{message.text}"/></div>
</f:view>
</body>
</html>

-----------------------------------------------------------------------------------------------------------------------
工作原理

当我们首次浏览 messages.jsp 页面时,无论是否由回传(postback)的JSF(页面请求)或浏览器直接的GET请求(非页面请求),此JSP页面将设法解析

messagelist 上下文变量。 由于上下文变量尚未被初始化,因此Seam将调用工厂方法 findmessages(),该方法执行了一次数据库查询并导致 DataModel 被向外注入。 DataModel 提供了渲染 <h:dataTable> 所需的行数据。

当用户点击 <h:commandLink> 时,JSF就调用 Select() 动作监听器。 Seam拦截此调用并将所选行的数据注入给 messageManager 组件的 message 属性。 而动作监听器将所选定的 Message 标为已读。在此调用结束时,Seam向外注入所选定的 Message 给名为 message 的变量。 接着,EJB容器提交事务,将 Message 的已读标记写入数据库。 最后,该网页重新渲染,再次显示消息列表,并在列表下方显示所选消息的内容。

如果用户点击了 <h:commandButton>,JSF就调用 delete() 动作监听器。 Seam拦截此调用并将所选行的数据注入给 messageManager 组件的 message 属性。 触发动作监听器,将选定的 Message 从列表中删除并同时在 EntityManager 中调用 remove() 方法。在此调用的最后,Seam刷新 messageList 上下文变量并清除名为 message 的上下文变量。 接着,EJB容器提交事务,将 Message 从数据库中删除。最后,该网页重新渲染,再次显示消息列表。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值