天天看點

第一個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) @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; 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) 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; public String register() { 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}"); return "/registered.jsp"; } else { 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>      

視圖層:

未完