第一个Seam2.0的Demo

开始Seam2.0的学习,首先来写第一个入门Demo--注册。

 

一、按照上一篇步骤创建SeamRegisterDemo.

1、首先写一个实体类

package org.su.reg.model; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import org.hibernate.validator.Length; import org.hibernate.validator.NotNull; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; @Entity // EJB标准注解@Entity表明了User类是个实体bean @Name("User") // Seam组件需要一个组件名称,由@Name指定。必须Seam应用内唯一 @Scope(ScopeType.SESSION) /*每当Seam实例化一个组件时,它就将始化后的实例绑定给组件中 默认上下文 的上下文变量。 * 默认的上下文由 @Scope注解指定。 UserBean是个会话作用域的组件*/ @Table(name = "users") //EJB标准注解@Table 表明了将 User 类映射到 users 表上。 public class User implements Serializable { private static final long serialVersionUID = 1881413500711441951L; private String username; private String password; private String name; /*name、 password 及 username 都是实体Bean的持久化属性。所有的持久化属性都定义了访问方法。 * 当JSF渲染输出及更新模型值阶段时需要调用该组件的这些方法。 * */ public String getUsername() { return username; } @Id @NotNull @Length(min=3,max=10) //标准EJB注解 @Id 表明是实体Bean的主键属性。 public void setUsername(String username) { this.username = username; } @NotNull @Length(min=3,max=10) public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @NotNull @Length(min=3,max=10) /*@NotNull 和 @Length 注解是Hibernate Validator框架的组成部份, * Seam集成了Hibernate Validator并让你用它来作为数据校验(尽管你可能并不使用Hibernate作为持久化层)。 */ public String getName() { return name; } public void setName(String name) { this.name = name; } public User(String name, String password, String username) { super(); this.name = name; this.password = password; this.username = username; } //EJB和Seam都要求有空的构造器。 public User() { } }

 

 

最值得注意的是 @Name@Scope 注解,它们确立了这个类是Seam的组件。

接下来我们将看到 User 类字段在更新模型值阶段时直接被绑定给JSF组件并由JSF操作, 在此并不需要冗余的胶水代码来在JSP页面与实体Bean域模型间来回拷贝数据。

然而,实体Bean不应该进行事务管理或数据库访问。故此,我们无法将此组件作为JSF动作监听器,因而需要会话Bean。

 

2、无状态会话Bean:RegisterAction.java

 

在Seam应用中大都采用会话Bean来作为JSF动作监听器(当然我们也可选择JavaBean)。

在此示例中,只有一个JSF动作,并且我们使用会话Bean方法与之相关联并使用无状态Bean,这是由于所有与动作相关的状态都保存在  UserBean中。

 

package org.su.reg.action; import java.util.List; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.faces.FacesMessages; import org.jboss.seam.log.Log; import org.su.reg.model.User; @Stateless // EJB标准注解 @Stateless 将这个类标记为无状态的会话Bean。 @Name("register") public class RegisterAction { @In // 注解 @In将Bean的一个属性标记为由Seam来注入。 在此例中,此属性由名为 user 的上下文变量注入(实例的变量名)。 private User user; @PersistenceContext // EJB标准注解 @PersistenceContext 用来注入EJB实体管理器。 private EntityManager em; @Logger // Seam的 @Logger 注解用来注入组件的 Log 实例。 private Log log; /* * 动作监听器方法使用标准的EJB3 EntityManager API来与数据库交互,并返回JSF的输出结果。 * 请注意,由于这是个会话Bean,因此当 register() 方法被调用时事务就会自动开始,并在结束时提交(commit)。 */ public String register() { /* * * 请注意Seam让你在EJB-QL中使用JSF EL表达式。因此可在标准JPA Query 对象上调用普通的JPA * setParameter() 方法, 这样岂不妙哉? */ List list = em.createQuery( "select username from User where username=#{user.username}") .getResultList(); if (list.size() == 0) { em.persist(list); // Log API为显示模板化的日志消息提供了便利。 log.info("Registered new user #{user.username}"); /* * * 多个JSF动作监听器方法返回一个字符串值的输出,它决定了接下来应显示的页面内容。 * 空输出(或返回值为空的动作监听器方法)重新显示上一页的内容。 在普通的JSF中, 用JSF的导航规则(navigation * rule) 来决定输出结果的JSF视图id是很常用的。 * 这种间接性对于复杂的应用是非常有用的,值得去实践。但是,对于象示例这样简单的的应用, * Seam让你使用JSF视图id作为输出结果,以减少对导航规则的需求。请注意,当你用视图id作为输出结果时, * Seam总会执行一次浏览器的重定向。 */ return "/registered.jsp"; } else { /* * * Seam提供了大量的 内置组件(built-in components) 来协助解决那些经常遇到的问题。 用 * FacesMessages 组件就可很容易地来显示模板化的错误或成功的消息。 内置的Seam组件还可由注入或通过调用 * instance() 方法来获取。 */ FacesMessages.instance() .add("User #{user.username} already exists"); System.out.println("Register successful."); return null; } } }

 

 

这次我们并没有显式指定 @Scope ,若没有显式指定时,每个Seam 组件类型就使用其默认的作用域。对于无状态的会话Bean, 其默认的作用域就是无状态的上下文。实际上 所有的 无状态的会话Bean都属于无状态的上下文。

会话Bean的动作监听器在此小应用中履行了业务和持久化逻辑。在更复杂的应用中,我们可能要将代码分层并重构持久化逻辑层成 专用数据存取组件,这很容易做到。但请注意Sean并不强制你在应用分层时使用某种特定的分层策略。

此外,也请注意我们的SessionBean会同步访问与web请求相关联的上下文(比如在 User 对象中的表单的值),状态会被保持在事务型的资源里(EntityManager 对象)。 这是对传统J2EE的体系结构的突破。再次说明,如果你习惯于传统J2EE的分层,也可以在你的Seam应用实行。但是对于许多的应用,这是明显的没有必要 。

 

3、会话Bean的本地接口:Register.java

很自然,我们的会话Bean需要一个本地接口。

@Local public interface Register { public String register(); }

 

所有的Java代码就这些了,现在去看一下部署描述文件。

 

4、web.xml

<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- Seam --> <listener> <listener-class>org.jboss.seam.servlet.SeamListener</listener-class> </listener> <!-- MyFaces --> <listener> <listener-class> org.apache.myfaces.webapp.StartupServletContextListener </listener-class> </listener> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>client</param-value> </context-param> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Faces Servlet Mapping --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.seam</url-pattern> </servlet-mapping> </web-app>

 

web.xml 文件配置了Seam和JSF。所有Seam应用中的配置与此处的配置基本相同。  

 

5.JSF配置:faces-config.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN" "http://java.sun.com/dtd/web-facesconfig_1_0.dtd"> <faces-config> <!-- A phase listener is needed by all Seam applications --> <lifecycle> <phase-listener>org.jboss.seam.jsf.SeamPhaseListener</phase-listener> </lifecycle> </faces-config>

 

注意我们不需要申明任何JSF managed Bean!因为我们所有的managed Bean都是通过经过注释的Seam组件。所以在Seam的应用中,faces-config.xml比原始的JSF更少用到。

实际上,一旦你把所有的基本描述文件配置完毕,你所需写的 唯一类型的 XML文件就是导航规则及可能的jBPM流程定义。对于Seam而言, 流程(process flow) 及 配置数据 是唯一真正属于需要XML定义的。

在此简单的示例中,因为我们将视图页面的ID嵌入到Action代码中,所以我们甚至都不需要定义导航规则。

 

 

 6.ejb-jar.xml 文件将 SeamInterceptor 绑定到压缩包中所有的会话Bean上,以此实现了Seam与EJB3的整合。

<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
         version="3.0">

   <interceptors>
     <interceptor>
       <interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
     </interceptor>
   </interceptors>

   <assembly-descriptor>
      <interceptor-binding>
         <ejb-name>*</ejb-name>
         <interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class>
      </interceptor-binding>
   </assembly-descriptor>

</ejb-jar>
 

persistence.xml 文件告诉EJB的持久化层在哪找到数据源,该文件也含有一些厂商特定的设定。此例在程序启动时自动创建数据库Schema。

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
             version="1.0">
    <persistence-unit name="userDatabase">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>java:/DefaultDS</jta-data-source>
      <properties>
         <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      </properties>
    </persistence-unit>
</persistence>

视图层:

 

未完

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值