相對于WEB工程來說,EJB工程的更改就不太多了,可以新建一個EJB工程,然后在源文件的根目錄下,也就是netbeans的default package下面,添加一個文件,叫seam.properties,無論你有沒有用到,也要添加這么一個文件,否則你的EJB工程就是一個普通的EJB工程了,就不能被SEAM所管理,并且里面的Session Bean就不能被用來當做JSF的backingbean,這一點要特別注意.然后就可以像建普通EJB一樣編寫EJB代碼了,你可以用netbeans來生成,也可以自己手工編寫,先編寫接口,再編寫Bean,這都無所謂.然后為了讓我們的EJB能被當做JSF的backingbean,我們需要在我們編寫的EJB里面添加如下注釋:@Name,它是SEAM框架帶的注釋,這就相當于聲明了一個backingbean,比如以下的類:
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
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;
/**
*
* @author hadeslee
*/
@Entity
@Name("user")
@Table(name = "users")
@Scope(ScopeType.SESSION)
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String password;
private String name;
@NotNull
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@NotNull @Length(min=5,max=15)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@NotNull @Length(min=5,max=15)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public void setId(Long id) {
this.id = id;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof User)) {
return false;
}
User other = (User) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "com.hadeslee.test1.User[id=" + id + "]";
}
}
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
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;
/**
*
* @author hadeslee
*/
@Entity
@Name("user")
@Table(name = "users")
@Scope(ScopeType.SESSION)
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String password;
private String name;
@NotNull
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@NotNull @Length(min=5,max=15)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@NotNull @Length(min=5,max=15)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public void setId(Long id) {
this.id = id;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof User)) {
return false;
}
User other = (User) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "com.hadeslee.test1.User[id=" + id + "]";
}
}
我這個EntityBean是用netbeans生成的,然后自己再添加一些內容,讓netbeans生成的好處是它可以自動為你生成equals和hashCode方法,在我們這個類里面,由于添加了@Name注釋,那么它的值user就可以當做一個backingbean的名字,而直接在JSF頁面里面使用了.至于別的注釋,等我們編寫第一個簡單的SEAM應用的時候再詳細解釋.
上面看到的是實體類,其實Session Bean也是一樣的,比如:
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;
/**
*
* @author hadeslee
*/
@Stateless
@Name("register")
public class RegisterAction implements Register {
@In
private User user;
@PersistenceContext
private EntityManager em;
@Logger
private Log log;
public String register() {
List existing = em.createQuery("select username from User where username=#{user.username}").getResultList();
if (existing.size() == 0) {
em.persist(user);
log.info("注冊了新的用戶,名字是: #{user.username}");
return "/registered.jsp";
} else {
FacesMessages.instance().add("用戶 #{user.username} 已經存在");
return null;
}
}
}
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;
/**
*
* @author hadeslee
*/
@Stateless
@Name("register")
public class RegisterAction implements Register {
@In
private User user;
@PersistenceContext
private EntityManager em;
@Logger
private Log log;
public String register() {
List existing = em.createQuery("select username from User where username=#{user.username}").getResultList();
if (existing.size() == 0) {
em.persist(user);
log.info("注冊了新的用戶,名字是: #{user.username}");
return "/registered.jsp";
} else {
FacesMessages.instance().add("用戶 #{user.username} 已經存在");
return null;
}
}
}
它也用了注釋:@Name,當我們在JSF頁面里面調用register的時候,就可以直接調用這個無狀態會話Bean的方法做為action了.這就是SEAM的特點,讓我們的JSF和EJB無縫的連接到了一起.
在SEAM里面,支持雙向注射,可以使用@In來注入,也可以用@Out來射出.
看完代碼之后,我們還要添加一個文件ejb-jar.xml,這個文件是EJB2.X的時候一定要用到的,當EJB3.0可以使用注釋以后,它就變成可有可無的了,但是為了SEAM能知道我們EJB里面的方法并攔截它,因為只有它能攔截我們的方法,才能在我們調用某個方法的時候,為我們注入我們需要的對象.
ejb-jar.xml里面的內容絕大多數情況內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<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>
<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>
它只是定義了一個攔截器,指定的一個攔截器,攔截此JAR包里面的所有的EJB方法調用.這個千萬不能少,否則的話,就不能在我們調用EJB方法之前注入我們需要的對象了.
當然,如果你使用了Entity bean的話,就會有persistence.xml了,它一般是由netbeans自動生成的,關于這個文件就和以前的一樣了,不用過多的介紹.
當然,我們還要說說EJB工程里面要引用到的庫文件,比如我們的@Name注釋和@In和@Out注釋,都是SEAM的包里面的.下面是一般要用到的庫文件:
jboss-seam.jar Seam的核心庫
其的它就不用了,其實很多庫,既可以和WEB的工程目錄相關,也可以和EJB的工程目錄相關,反正最后是一個Enterprise Application,會把WEB和EJB的工程統一打包成EAR文件的.
關于前面的配置就這些了,其實SEAM的配置也不是很復雜,對于WEB工程來說,只是加了幾個XML文件,而對于EJB工程來說,幾乎什么都沒有加,只是加了一個SEAM的核心庫而已.
下一章,我們將用Netbeans開發一個完整的SEAM應用,一個非常簡單的SEAM應用,接受注冊,以及驗證輸入.如果驗證通過就把輸入的內容保存到數據庫里面.
盡管千里冰封
依然擁有晴空
你我共同品味JAVA的濃香.