EJB整理4-拦截器

    技术2022-06-12  48

     

    1       拦截器

    拦截器可以拦截 Session bean message-driven bean 的方法调用或生命周期事件。拦截器用于封装应用的公用行为,使这些行为与业务逻辑分离,一旦这些公用行为发生改变,而不必修改很多业务类。拦截器可以是同一bean类中的方法或是一个外部类。

    下面介绍如何在 Session Bean 类中使用外部拦截器类。

    HelloChinaBean.java

    @Stateless @Local(HelloChina.class) @Interceptors(HelloInterceptor.class) public class HelloChinaBean implements HelloChina{ public String SayHello(String name) { return name +"说:你好!中国."; } public String Myname() { return "我是中国人"; } }  

    @Interceptors  注释指定一个或多个在外部类中定义的拦截器,多个拦截器类之间用逗号分隔,如:@Interceptors({A.class,A.class,B.class}),如果只有一个拦截器可以省略大括号。上面拦截器 HelloInterceptor HelloChinaBean 的所有方法进行拦截。如果你只需对某一方法进行拦截,你可以在方法上面定义拦截器,如:

    public class HelloChinaBean implements HelloChina{ @Interceptors(HelloInterceptor.class) public String SayHello(String name) { return name +"说:你好!中国."; } } 拦截器 HelloInterceptor.java

    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 的定义:

    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"); } }  

     


    最新回复(0)