拦截器(Interceptor)
拦截器可以监听程序的一个或所有方法。拦截器对方法调用流提供了细粒度控制。可以在无状态会话bean、有状态会话bean 和消息驱动bean 上使用它们。拦截器可以是同一bean 类中的方法或是一个外部类。
拦截器可以监听程序的一个或所有方法。拦截器对方法调用流提供了细粒度控制。可以在无状态会话bean、有状态会话bean 和消息驱动bean 上使用它们。拦截器可以是同一bean 类中的方法或是一个外部类。
下面介绍如何在Session Bean 类中使用外部拦截器类。
HelloChinaBean.java
HelloChinaBean.java
package com.foshanshop.ejb3.impl;
import com.foshanshop.ejb3.HelloChina;
import com.foshanshop.ejb3.HelloChinaRemote;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
@Stateless
@Remote (HelloChinaRemote.class)
@Local(HelloChina.class)
@Interceptors(HelloInterceptor.class)
public class HelloChinaBean implements HelloChina,HelloChinaRemote {
public String SayHello(String name) {
return name +"说:你好!中国.";
}
public String Myname() {
return "我是佛山人";
}
}
如果你只需对某一方法进行拦截,你可以在方法上面定义拦截器,如:
public class HelloChinaBean implements HelloChina,HelloChinaRemote {
@Interceptors(HelloInterceptor.class)
public String SayHello(String name) {
return name +"说:你好!中国.";
}
}
HelloInterceptor
package com.foshanshop.ejb3.impl;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
public class HelloInterceptor {
@AroundInvoke
public Object log(InvocationContext ctx) throws Exception {
System.out.println("*** HelloInterceptor intercepting");
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) {
throw e;
}finally {
long time = System.currentTimeMillis() - start;
System.out.println("用时:"+ time + "ms");
}
}
}
@AroundInvoke 注释指定了要用作拦截器的方法,拦截器方法与被拦截的业务方法执行在同一个java 调用堆栈、
同一个事务和安全上下文中。用@AroundInvoke 注释指定的方法必须遵守以下格式:
public Object XXX(javax.interceptor.InvocationContext ctx) throws Exception
XXX 代表方法名可以任意。javax.interceptor.InvocationContext 封装了客户端所调用业务方法的一些信息。下面是
InvocationContext 的定义:
package javax.interceptor;
public interface InvocationContext {
public Object getTarget( );
public Method getMethod( );
public Object[] getParameters( );
public void setParameters(Object[] newArgs);
public java.util.Map<String, Object> getContextData( );
public Object proceed( ) throws Exception;
}
getTarget( ) 指向被调用的bean 实例
getMethod( ) 指向被拦截的业务方法
getParameters( ) 获取被拦截业务方法的参数
setParameters() 设置被拦截业务方法的参数
getContextData( ) 方法返回一个Map 对象,它在整个方法调用期间都可以被访问到。位于同一方法调用内的不同
拦截器之间可以利用它来传递上下文相关的数据。
在HelloInterceptor 代码中,我们调用了ctx.proceed()方法。如果还有其它拦截器未执行,ctx.proceed()方法内部会
调用后面拦截器的@AroundInvoke 方法,直到后面的拦截器全部执行结束,EJB 容器才会执行被拦截的业务方法。
ctx.proceed()方法必须在拦截器代码中被调用,否则被拦截的业务方法就根本不会被执行。另外如果我们想在被拦
截的业务方法执行结束后再执行一些自定义代码,我们可以在ctx.proceed()执行后方法返回前加入自己的代码,
如:
同一个事务和安全上下文中。用@AroundInvoke 注释指定的方法必须遵守以下格式:
public Object XXX(javax.interceptor.InvocationContext ctx) throws Exception
XXX 代表方法名可以任意。javax.interceptor.InvocationContext 封装了客户端所调用业务方法的一些信息。下面是
InvocationContext 的定义:
package javax.interceptor;
public interface InvocationContext {
public Object getTarget( );
public Method getMethod( );
public Object[] getParameters( );
public void setParameters(Object[] newArgs);
public java.util.Map<String, Object> getContextData( );
public Object proceed( ) throws Exception;
}
getTarget( ) 指向被调用的bean 实例
getMethod( ) 指向被拦截的业务方法
getParameters( ) 获取被拦截业务方法的参数
setParameters() 设置被拦截业务方法的参数
getContextData( ) 方法返回一个Map 对象,它在整个方法调用期间都可以被访问到。位于同一方法调用内的不同
拦截器之间可以利用它来传递上下文相关的数据。
在HelloInterceptor 代码中,我们调用了ctx.proceed()方法。如果还有其它拦截器未执行,ctx.proceed()方法内部会
调用后面拦截器的@AroundInvoke 方法,直到后面的拦截器全部执行结束,EJB 容器才会执行被拦截的业务方法。
ctx.proceed()方法必须在拦截器代码中被调用,否则被拦截的业务方法就根本不会被执行。另外如果我们想在被拦
截的业务方法执行结束后再执行一些自定义代码,我们可以在ctx.proceed()执行后方法返回前加入自己的代码,
如:
@AroundInvoke
public Object log(InvocationContext ctx) throws Exception {
System.out.println("*** HelloInterceptor intercepting");
long start = System.currentTimeMillis();
try{
Object o = ctx.proceed();
//这里加入你需要执行的代码
return o;
}catch (Exception e) {
throw e;
}finally {
long time = System.currentTimeMillis() - start;
System.out.println("用时:"+ time + "ms");
}
}
将Session Bean 中的一个或多个方法定义为拦截器,只需一个@AroundInvoke 注释就指定了要用作拦截器的方法。
package com.foshanshop.ejb3.impl;
import com.foshanshop.ejb3.HelloChina;
import com.foshanshop.ejb3.HelloChinaRemote;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
@Stateless
@Remote ({HelloChinaRemote.class})
@Local(HelloChina.class)
public class HelloChinaBean implements HelloChina,HelloChinaRemote {
public String SayHello(String name) {
return name +"说:你好!中国.";
}
public String Myname() {
return "我是佛山人";
}
@AroundInvoke
public Object log(InvocationContext ctx) throws Exception {
try{
if (ctx.getMethod().getName().equals("SayHello")){
System.out.println("*** HelloChinaBean.SayHello() 已经被调用! *** " );
}
if (ctx.getMethod().getName().equals("Myname")){
System.out.println("*** HelloChinaBean.Myname() 已经被调用! *** " );
}
return ctx.proceed();
}catch (Exception e) {
throw e;
}
}