SEAM学习(2)-messages示例
SEAM学习(二)---messages示例
实体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 从数据库中删除。最后,该网页重新渲染,再次显示消息列表。
实体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 从数据库中删除。最后,该网页重新渲染,再次显示消息列表。