1.拦截器综述

拦截器的功能是定义在Java拦截器规范。

拦截器规范定义了三种拦截点:

业务方法拦截,
生命周期回调侦听,
超时拦截(EJB)方法。
在容器的生命周期中进行拦截

public class DependencyInjectionInterceptor {@PostConstructpublic void injectDependencies(InvocationContext ctx) { ... }
}

EJB超时时使用的拦截器

public class TimeoutInterceptor {@AroundTimeoutpublic Object manageTransaction(InvocationContext ctx) throws Exception { ... }
}

在业务上,对某一个Bean的方法进行拦截

public class TransactionInterceptor {@AroundInvokepublic Object manageTransaction(InvocationContext ctx) throws Exception { ... }
}

@AroundInvoke注释指定了要用作拦截器的方法,拦截器方法与被拦截的业务方法执行同一个java调用堆栈、同一个事务和安全上下文中。用@AroundInvoke注释指定的方法必须遵守以下格式:public Object XXX(javax.interceptor.InvocationContext ctx) throws Exception

下面是javax.interceptor.InvocationContext封装了客户端所调用业务方法的一些信息。

package javax.interceptor;
public interface InvocationContext{public Object getTarget();public Method getMethod();public Ojbect[] getParameters();public void setParameters(Object[] newArgs);public java.util.Map<String, Ojbect> getContextData();public Object proceed() throws Exception;
}

getTarget() 指向被调用的bean实例
getMethod() 指向被拦截的业务方法
getParameters() 获取被拦截业务方法的参数
setParameters() 设置被拦截业务方法的参数
getContextData() 返回一个Map对象,它在整个方法调用期间都可以被访问到。位于同一个方法调用内的不同拦截器之间可以利用它来传递上下文相关的数据。
示例:

//被拦截的方法
@Interceptors(HelloInterceptor.class)
public class HelloChinaBean {public String SayHello(String name) {return name +"Hello World.";}
}
//拦截器定义
public class HelloInterceptor {@AroundInvokepublic Object log(InvocationContext ctx) throws Exception {try{if (ctx.getMethod().getName().equals("SayHello")){System.out.println("Holle World!!!" );}           return ctx.proceed();}catch (Exception e) {throw e;}}
}

2.拦截器绑定(Interceptor bindings)

假设我们想要申明一些bean的事务。我们先要的是一个拦截器绑定类型来指定哪些bean我们要申明.
首先定义一个注解

@InterceptorBinding
@Target({METHOD, TYPE})
@Retention(RUNTIME)
public @interface Transactional {}
现在我们可以很容易地指定类ShoppingCart是事务性对象:

@Transactional public class ShoppingCart { ... } 或者我们可以指定一个方法的事务

public class ShoppingCart {@Transactional public void checkout() { ... }
}

2.拦截器实现(Implementing interceptors)

我们实际上要实现提供了这种事务管理方面的拦截器,所以我们需要做的是创建一个标准的拦截,并配上@Interceptor和@transactional注解.

@Transactional @Interceptor
public class TransactionInterceptor {@AroundInvokepublic Object manageTransaction(InvocationContext ctx) throws Exception { ... }
}

拦截器可以利用依赖注入:

@Transactional @Interceptor
public class TransactionInterceptor {@Resource UserTransaction transaction;@AroundInvokepublic Object manageTransaction(InvocationContext ctx) throws Exception { ... }
}

多个拦截器可以使用相同的拦截器绑定类型。

@Resource和@Inject的区别:

3.启用拦截器(Enabling interceptors)

默认情况下,所有拦截器被禁用.要使用拦截器.需要在bean.xml中进行配置,以启用.从CDI 1.1起拦截器可以使用@Priority注释为整个应用程序启用。

<beansxmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"><interceptors><class>org.mycompany.myapp.TransactionInterceptor</class></interceptors>
</beans>

这样有2个好处:

拦截器比较重要,在XML中确保其确定性行为
它让我们在部署时启用或禁用拦截器类。
当然也可以配置启用多个拦截器

<beansxmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"><interceptors><class>org.mycompany.myapp.SecurityInterceptor</class><class>org.mycompany.myapp.TransactionInterceptor</class></interceptors>
</beans>

拦截器毕竟比较重要,不推荐使用@Priority启用.
在CDI中,XML配置的优先级高于@Priority.
关于@Priority可以参考下列:

public static class Interceptor.Priority
extends Object
Priorities that define the order in which interceptors are invoked. These values should be used with the Priority annotation.

Interceptors defined by platform specifications should have priority values in the range PLATFORM_BEFORE up until LIBRARY_BEFORE, or starting at PLATFORM_AFTER.
Interceptors defined by extension libraries should have priority values in the range LIBRARY_BEFORE up until APPLICATION, or LIBRARY_AFTER up until PLATFORM_AFTER.
Interceptors defined by applications should have priority values in the range APPLICATION up until LIBRARY_AFTER.
An interceptor that must be invoked before or after another defined interceptor can choose any appropriate value.

Interceptors with smaller priority values are called first. If more than one interceptor has the same priority, the relative order of these interceptor is undefined.

For example, an extension library might define an interceptor like this:

@Priority(Interceptor.Priority.LIBRARY_BEFORE+10)@Interceptorpublic class ValidationInterceptor { ... }

4.Interceptor bindings with members(拦截器注解属性)
假设我们想要添加一些额外的信息给我们的@transactional注解:

@InterceptorBinding
@Target({METHOD, TYPE})
@Retention(RUNTIME)
public @interface Transactional {boolean requiresNew() default false;
}

CDI将使用requiresNew的值选择两个不同的拦截器,TransactionInterceptor和RequiresNewTransactionInterceptor

下面是requiresNew为true的拦截器

@Transactional(requiresNew = true) @Interceptor
public class RequiresNewTransactionInterceptor {@AroundInvokepublic Object manageTransaction(InvocationContext ctx) throws Exception { ... }
}

如下使用:

@Transactional(requiresNew = true)
public class ShoppingCart { ... }

但是如果我们只有一个拦截器,我们希望容器拦截器绑定时忽略requiresNew的值,也许这些信息只用于拦截器实现。我们可以使用@Nonbinding注释:

@InterceptorBinding
@Target({METHOD, TYPE})
@Retention(RUNTIME)
public @interface Secure {@Nonbinding String[] rolesAllowed() default {};
}

5.Multiple interceptor binding annotations(多重拦截器绑定注解)

通常我们使用拦截器绑定的组合类型绑定多个拦截器bean。例如,下面的声明将用于绑定TransactionInterceptor和SecurityInterceptor这2个拦截器到ShoppingCart.

@Secure(rolesAllowed="admin") @Transactional
public class ShoppingCart { ... }

然而,在非常复杂的情况下,一个拦截器本身可能指定拦截器绑定类型:

@Transactional @Secure @Interceptor
public class TransactionalSecureInterceptor { ... }

那么这个拦截器可以绑定到checkout() 方法,以下任何组合都可使用:

public class ShoppingCart {@Transactional @Secure public void checkout() { ... }
}
@Secure
public class ShoppingCart {@Transactional public void checkout() { ... }
}
@Transactional
public class ShoppingCart {@Secure public void checkout() { ... }
}
@Transactional @Secure
public class ShoppingCart {public void checkout() { ... }
}

6. Interceptor binding type inheritance(拦截器绑定类型继承)

Java语言支持注解的一个限制就是缺乏注解继承.注解应该重用内置已有的.就如同下面这段代码表达的意思

//实际没这写法
public @interface Action extends Transactional, Secure { ... }

幸运的是,CDI围绕Java没有的这个特性开展了一些工作.
我们会标注一个拦截器绑定类型,其有其他拦截器的绑定类型,(称为元注解)
表述起来有点费劲,就如同下面代码这样.

@Transactional @Secure
@InterceptorBinding
@Target(TYPE)
@Retention(RUNTIME)
public @interface Action { ... }

现在任何Bean绑定 Action这个注解 ,其实就是绑定到了@Transactional @Secure.(就是拦截器TransactionInterceptor和拦截器SecurityInterceptor). (甚至TransactionalSecureInterceptor,如果它存在.)

7.Use of @Interceptors(同时用多个拦截器)
这个注解@Interceptors是拦截器规范定义的,cdi是支持的<使用托管bean和EJB规范>.如下:

@Interceptors({TransactionInterceptor.class, SecurityInterceptor.class})
public class ShoppingCart {public void checkout() { ... }
}

但缺点也很明显,不推荐使用.缺点如下:

拦截器在代码中是硬编码.
拦截器在部署时不好更改.
拦截器命令是非全局的——它是在类级别由拦截器的顺序列出.
因此还是使用上面CDI的使用方式比较好.

工作总结4:拦截器的使用相关推荐

  1. Struts2→拦截器、工作原理、拦截器计算Action执行时间、Struts2自带拦截器、拦截器栈

    工作原理 实现拦截器 样例 Struts2自带拦截器 拦截器栈(先进后出) TOKEN防表单重复提交 文字拦截器 AJAX

  2. SpringMVC→拦截器、SpringMVC拦截器实现、多个拦截器工作原理、拦截器使用场景、拦截器Interceptor与过滤器Filter区别

    拦截器 拦截器实现 多个拦截器工作原理 拦截器使用场景 请求编码设置及请求登录Session校验 使用时间段设置 拦截器Interceptor与过滤器Filter区别

  3. SpringMVC工作总结001_SpringMVC拦截器(资源和权限管理)

    1.DispatcherServlet SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServlet.     DispatcherServl ...

  4. 排队器拦截_过滤器(Filter)和拦截器(Interceptor)的执行顺序和区别

    首先建立一个SpringBoot工程,增加一个IndexController供测试使用. @Controller public class IndexController { @GetMapping( ...

  5. zuul 之拦截器深入浅出

    文章目录 Zuul Filter工作原理 Filter拦截器概述 流程图介绍 Inbound Filters [入口拦截] EndPoint Filters [终点拦截] Outbound Filte ...

  6. Spring拦截器(Interceptor)的运用

    在以Spring为基础的框架(例如Spring boot, Spring MVC)中,会使用到一种名为拦截器的东西,它属于面向切面编程的架构模式,为我们在API调用前后做一些额外操作提供了便利. 如何 ...

  7. struts2拦截器总结

    以下是struts2拦截器的内容: Struts2运转流程图: 10.jpg 其实拦截器Interceptors是struts2的最核心的内容,拦截器支撑起了struts2整个的运转流程. 要想理解拦 ...

  8. 过滤器(Filter)与拦截器(Interceptor )区别(转)

    原文地址:https://www.cnblogs.com/junzi2099/p/8022058.html#_labelTop 原文地址:https://www.cnblogs.com/junzi20 ...

  9. 第九篇——Struts2的拦截器

    拦截器: Struts2大多数核心功能都是通过拦截器实现的,每个拦截器完成某项功能: 拦截器方法在Action执行之前或之后执行. 工作原理: 拦截器的执行过程是一个递归的过程 action请求--& ...

  10. ABP 拦截器不工作

    想写个拦截器,但是按照官方教程,发现自定义的拦截器不工作. 经过排查发现是需要顶要你要被拦截的方法为虚方法才能功能. 先贴两个链接. 后面再找解决办法 为什么我的拦截器不工作 为什么拦截器在non-v ...

最新文章

  1. 马塞洛·里皮 - 简介
  2. C#:在Task中使用依赖注入的Service/EFContext
  3. 代码整洁之道的一些总结
  4. SQLServer 维护脚本分享(05)内存(Memory)
  5. http 与https 区别浅析
  6. windows打流工具IxChariot使用教程
  7. Java Web开发流程
  8. psasp和matlab,PSASP与Matlab/SimPowerSystems联合仿真接口方法研究
  9. php 限定字符长度,PHP中字符串的最大长度是多少?
  10. Java 创建一个Customer类,类中的属性有姓名、年龄、性别,然后创建两个Customer对象,把这两个对象存储在ArrayList对象中,然后再从ArrayList对象中读取出来。
  11. 禾穗HERS | 听说妳事业成功都是靠“关系”?
  12. seLinux的管理
  13. eva新世纪福音战士_新世纪福音战士EVA,一部划时代的作品!
  14. 闭合导线的近似平均差(工程测量)
  15. SylixOS中APIC HPET定时器字符驱动实现
  16. 启动QQ时无法访问个人文件夹XXX,是否自动修复个人文件夹权限
  17. 4.面向对象:封装,多态
  18. 小傻蛋的妹妹跟随小甲鱼学习Python的第八节008
  19. 加载图片的方法(I)
  20. 2021年平面设计师、游戏建模师电脑配置推荐,史上最全的配置单

热门文章

  1. 一个swiper 两个分页器的写法【总结】
  2. 实际算法项目工程上手日志C/C++
  3. 学习flex布局(弹性布局)
  4. maven+jetty项目在tomcat部署
  5. 安装配置Eclipse开发PHP环境配置
  6. 从流水中倒推算出销量为多某值的日期
  7. Ajax技术的基本原理
  8. sql获取某列出现频次最多的值_业务硬核SQL集锦
  9. 【 Grey Hack 】加强版nmap
  10. Java 基础——类的加载