今天主要是看了一下攔截器的實現,在EJB3.0里面,實現攔截非常簡單.加一個注釋就可以了,這樣就可以隨時監視某個方法的調用了,攔截器可以是攔截某一個方法也可以是攔截一個類的所有方法的.具體如下
首先寫一個攔截器方法,攔截器方法并不需要實現什么接口,只要符合一定的規范就可以了,
規范是: Object xxxxx(InvocationContext context)throws Exception,其中xxxxx是方法名,可以自己取.然后用@AroundInvoke來注釋這個方法
/*
* MyInterceptor.java
*
* Created on 2007年9月8日, 上午12:04
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package lbf.interceptor;
import java.lang.reflect.Method;
import java.util.Date;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import lbf.test1.Person;
/**
*
* @author Admin
*/
public class MyInterceptor {
/**
* Creates a new instance of MyInterceptor
*/
public MyInterceptor() {
}
@AroundInvoke
public Object myInter(InvocationContext context)throws Exception{
if(context.getMethod().getName().equals("insertPerson")){
System.out.println("插入新的Person被調用了");
}else{
System.out.println("其它方法被調用了");
}
return context.proceed();
}
}
然后,同樣是聲明遠程接口和實現它的類,為了讓攔截顯得更有效果,我們聲明一個實體Bean,把一個實體插入數據庫是我們的工作,然后我們再攔截它,看看會怎么樣
/*
* Person.java
*
* Created on 2007年9月7日, 下午10:46
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package lbf.test1;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* 實體類 Person
*
* @author Admin
*/
@Entity
public class Person implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="PersonID",nullable=false)
private Integer id;
@Column(name="PersonName",nullable=false,length=5)
private String name;
@Column(name="PersonAge")
private int age;
@Column(name="PersonSex",nullable=false,length=2)
private String sex;
@Column(name="PersonPhone",nullable=false,length=11)
private String phone;
@Column(name="PersonAddress",nullable=false,length=50)
private String address;
@Temporal(value = TemporalType.DATE)
@Column(name="PersonBirthday")
private Date birthday;
/** Creates a new instance of Person */
public Person() {
}
/**
* 獲取此 Person 的 id。
* @return id
*/
public Integer getId() {
return this.id;
}
/**
* 將此 Person 的 id 設置為指定的值。
* @param id,新建 id
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 返回對象的散列代碼值。該實現根據此對象
* 中 id 字段計算散列代碼值。
* @return 此對象的散列代碼值。
*/
@Override
public int hashCode() {
int hash = 0;
hash += (this.id != null ? this.id.hashCode() : 0);
return hash;
}
/**
* 確定其他對象是否等于此 Person。當且僅當
* 參數不為 null 且該參數是具有與此對象相同 id 字段值的 Person 對象時,
* 結果才為 true。
* @param 對象,要比較的引用對象
* 如果此對象與參數相同,則 @return true;
* 否則為 false。
*/
@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 Person)) {
return false;
}
Person other = (Person)object;
if (this.id != other.id && (this.id == null || !this.id.equals(other.id))) return false;
return true;
}
/**
* 返回對象的字符串表示法。該實現根據 id 字段
* 構造此表示法。
* @return 對象的字符串表示法。
*/
@Override
public String toString() {
return "lbf.test1.Person[id=" + id + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
java 代碼,PersonDAO的實現
/*
* PersonBean.java
*
* Created on 2007年9月7日, 下午11:10
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package lbf.test1;
import java.util.List;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import lbf.interceptor.MyInterceptor;
/**
*
* @author Admin
*/
@Remote(PersonDAO.class)
@Stateless
@Interceptors({MyInterceptor.class})
public class PersonBean implements PersonDAO{
@PersistenceContext
private EntityManager em;
/** Creates a new instance of PersonBean */
public PersonBean() {
}
public boolean insertPerson(Person person) {
try{
em.persist(person);
}catch(Exception exe){
exe.printStackTrace();
return false;
}
return true;
}
public String getPersonNameByID(int personid) {
Person p=em.find(Person.class,personid);
return p.getName();
}
public boolean updatePerson(Person person) {
try{
em.merge(person);
}catch(Exception exe){
exe.printStackTrace();
return false;
}
return true;
}
public Person getPersonByID(int personid) {
return em.find(Person.class,personid);
}
public List getPersonList(int max, int whichpage) {
try {
int index = (whichpage-1) * max;
Query query = em.createQuery("from Person p order by personid asc");
List list = query.setMaxResults(max).
setFirstResult(index).
getResultList();
em.clear();//分離內存中受EntityManager管理的實體bean,讓VM進行垃圾回收
return list;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
/*
* PersonDAO.java
*
* Created on 2007年9月7日, 下午11:10
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package lbf.test1;
import java.util.Date;
import java.util.List;
/**
*
* @author Admin
*/
public interface PersonDAO {
public boolean insertPerson(Person person);
public String getPersonNameByID(int personid);
public boolean updatePerson(Person person);
public Person getPersonByID(int personid);
public List getPersonList(int max,int whichpage);
}
所有的類都定義好了,我們現在開始試用攔截器了
我們聲明一個主類去調用PersonBean的一些方法
/*
* Main.java
*
* Created on 2007年9月7日, 下午10:37
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package lbf.client;
import java.util.Date;
import java.util.Properties;
import javax.naming.InitialContext;
import lbf.test1.Person;
import lbf.test1.PersonDAO;
/**
*
* @author Admin
*/
public class Main {
private InitialContext ctx;
/** Creates a new instance of Main */
public Main() {
initContext();
}
private void initContext(){
try{
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.provider.url", "localhost:1099");
props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
ctx = new InitialContext(props);
}catch(Exception exe){
exe.printStackTrace();
}
}
private void doPerson(){
try{
PersonDAO dao=(PersonDAO)ctx.lookup("PersonBean/remote");
Person pp=new Person();
pp.setAddress("香蓮里33號20C");
pp.setAge(20);
pp.setBirthday(new Date());
pp.setName("千里冰封");
pp.setPhone("12536214");
pp.setSex("男");
System.out.println("成功嗎?"+dao.insertPerson(pp));
}catch(Exception exe){
exe.printStackTrace();
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
Main main=new Main();
main.doPerson();
}
}
在我們執行Main的時候,會看到JBOSS的標準輸出會輸出一句
"插入新的Person被調用了"
如果我們調用其它的方法,就會輸出"其它方法被調用了"
到這里,我想到一個問題,我們攔截的時候只是為了輸出這句話嗎,我能不能攔截一些別的東西呢,比如,我保存Person的時候,如果Person的姓名不合法,我可不可以檢查一下,然后再插入別的,或者我直接換掉原來的調用,調用我自己的東西.行嗎?還是試一下先吧,我們把myInter方法換成如下的樣子
@AroundInvoke
public Object myInter(InvocationContext context)throws Exception{
if(context.getMethod().getName().equals("insertPerson")){
System.out.println("插入新的Person被調用了");
Method m=context.getMethod();
Person person=new Person();
person.setAddress("被換成的地址");
person.setAge(10);
person.setBirthday(new Date());
person.setName("被換的名字");
person.setPhone("1380606");
person.setSex("男");
return m.invoke(context.getTarget(),person);
}else{
System.out.println("其它方法被調用了");
}
return context.proceed();
}
加了幾句自己的東東,然后直接把要調用的Method取出來,自己去調用它.然后返回它所應該返回的東西
這個時候,你會發現,當你在調用PersonBean上的insertPerson的時候,你自己要插入的Person被我們改了,插入的是我們攔截器里面的Person.
使用攔截器如果只能這樣的話,那豈不是也不太好,想像一下,如果我寫一個類的時候,沒有使用@Interceptors來注釋它使用哪個攔截器,后來我又想攔截它了,豈不是要重新注釋一下編譯一下然后再布署?這樣豈不是太麻煩了.有沒有別的方法呢
方法當然有,那就是回歸到最原始的用XML方法來配置,用XML方法配置以后,就不管你的Bean有沒有使用@Interceptors來注釋,它都會按照你聲明的內容來進行攔截了,這樣就比直接用注釋靈活性大了很多了.XML的聲明如下
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns = "http://java.sun.com/xml/ns/javaee"
version = "3.0"
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">
<assembly-descriptor>
<interceptor-binding>
<ejb-name>PersonBean</ejb-name>
<interceptor-class>lbf.interceptor.MyInterceptor</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
</ejb-jar>
這個XML名字叫做ejb-jar.xml,布署的時候,要把它放在META-INF文件夾里面.所有可以用注釋來解決的,其實都可以用XML來配置,EJB3.0之前就是因為XML配置太麻煩才被人說的,我們也不希望完全使用XML來配置,但是在有些情況下,用XML來配置確實是比較靈活.不像用注釋配置是硬編碼class文件里面去的,如果要改的話,還得用源代碼重新編譯一下.而XML要改就方法多了,改了以后重新打一下包就可以了,所以是選擇注釋來配置還是XML來配置,就要看具體的要求了.
盡管千里冰封
依然擁有晴空
你我共同品味JAVA的濃香.
posted on 2007-09-08 10:24
千里冰封 閱讀(1017)
評論(0) 編輯 收藏 所屬分類:
JAVAEE