EJB初学日记(3)

本文介绍如何在EJB3.0中利用注解和XML配置实现方法调用的拦截器,演示了如何自定义拦截逻辑及改变传入参数,并探讨了注解与XML配置的不同适用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2007年10月10日 07:10:00

今天主要是看了一下拦截器的实现,在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来配置,就要看具体的要求了.


来自:EJB初学日记(3)



Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=1817698


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值