拦截器可以拦截Session Bean和Message-Driven Bean的方法调用或生命周期事件。拦截器用于封装应用的公共行为,是这些行为和业务逻辑分离。
拦截器可以是同一个bean类中的方法或者是一个外部类。
@Interceptor注释指定一个或者多个在外部类中定义的拦截器,多个拦截器之间用逗号分隔。如果只需要对某一个方法进行拦截,可以在方法上定义拦截器。
package com.manfred.ejb.impl;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import com.manfred.ejb.HelloChina;
import com.manfred.ejb.HelloChinaRemot;
@Stateless
@Remote({ HelloChinaRemot.class })
@Local({ HelloChina.class })
@Interceptors({ HelloInterceptor.class })
public class HelloChinaBean implements HelloChinaRemot {
public String sayHello(String name) {
return name + "说,你好!中国";
}
public String Myname() {
return "Manfred Shuai";
}
}
package com.manfred.ejb.impl;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
public class HelloInterceptor {
@AroundInvoke
public Object log(InvocationContext ctx) throws Exception{
System.out.println("****HelloInterceptor interception......");
long start = System.currentTimeMillis();
try{
if(ctx.getMethod().getName().equals("sayHello")){
System.out.println("***sayHello方法已经被调用****");
}
if(ctx.getMethod().getName().equals("Myname")){
System.out.println("***myName方法已经被调用****");
}
return ctx.proceed();
} catch(Exception e){
e.printStackTrace();
throw e;
}finally {
long time = System.currentTimeMillis() -start;
System.out.println("用时: " + time + "ms");
}
}
}
InvocationContext的定义有
getTarget():指向被拦截的bean实例,返回值为Object
getMethod():指向被拦截的业务方法,返回值为Method
getParameters():获取被拦截业务方法的参数,返回值为Object[]
setParameters():设置被拦截业务方法的参数,无返回值
getContextData():方法返回一个对象,它在整个方法调用期间都能够被反问道。位于同一个方法调用内的不同拦截器之间可以利用它来传递上下文的数据和信息
proceed():如果其它拦截器未执行,该方法为调用后面拦截器的@AroundInvoke方法,知道所有拦截器的方法都全部执行完毕了,EJB容器才会执行被拦截的业务方法。这个方法必须在拦截器代码中被调用,否则被拦截的业务方法根本就不会被执行。另外,如果现在被拦截的业务方法执行结束以后再执行一段自定义代码,可以在proceed()执行方法返回前加入自己的代码。
由于拦截器和被拦截的bean业务方法同处于一个java调用堆栈中,如果希望终止bean业务方法的执行,可以考虑通过抛出异常的方式来处理。
在一个EJB模块中通常有许多EJB,如果需要对所有的EJB的方法进行拦截,为每一个EJB加入@Interceptor注释,显然很繁琐,为此提供了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">
<assembly-descriptor>
<interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-class>com.manfred.ejb.impl.HelloInterceptor</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
</ejb-jar>
ejb-jar.xml文件放置到jar文件的META-INF目录中,部署即可(如果是j通过sp页面验证,可能也需要重新发布jsp的jar包)