千里冰封
JAVA 浓香四溢
posts - 151,comments - 2801,trackbacks - 0

今天主要是看了一下拦截器的实现,在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 千里冰封 阅读(1015) 评论(0)  编辑  收藏 所属分类: JAVAEE

只有注册用户登录后才能发表评论。


网站导航: