CDI services--interceptors(拦截器)
1.拦截器综述
拦截器的功能是定义在Java拦截器规范。
拦截器规范定义了三种拦截点:
- 业务方法拦截,
- 生命周期回调侦听,
- 超时拦截(EJB)方法。
在容器的生命周期中进行拦截
|
1
2
3
4
|
public class DependencyInjectionInterceptor { @PostConstruct public void injectDependencies(InvocationContext ctx) { ... }} |
EJB超时时使用的拦截器
|
1
2
3
4
5
|
public class TimeoutInterceptor { @AroundTimeout public Object manageTransaction(InvocationContext ctx) throws Exception { ... }} |
在业务上,对某一个Bean的方法进行拦截
|
1
2
3
4
5
|
public class TransactionInterceptor { @AroundInvoke public Object manageTransaction(InvocationContext ctx) throws Exception { ... }} |
@AroundInvoke注释指定了要用作拦截器的方法,拦截器方法与被拦截的业务方法执行同一个java调用堆栈、同一个事务和安全上下文中。用@AroundInvoke注释指定的方法必须遵守以下格式:public Object XXX(javax.interceptor.InvocationContext ctx) throws Exception
下面是javax.interceptor.InvocationContext封装了客户端所调用业务方法的一些信息。
|
1
2
3
4
5
6
7
8
9
|
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对象,它在整个方法调用期间都可以被访问到。位于同一个方法调用内的不同拦截器之间可以利用它来传递上下文相关的数据。
示例:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//被拦截的方法@Interceptors(HelloInterceptor.class)public class HelloChinaBean { public String SayHello(String name) { return name +"Hello World."; }}//拦截器定义public class HelloInterceptor { @AroundInvoke public 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我们要申明.
首先定义一个注解
|
1
2
3
4
|
@InterceptorBinding@Target({METHOD, TYPE})@Retention(RUNTIME)public @interface Transactional {} |
现在我们可以很容易地指定类ShoppingCart是事务性对象:
|
1
2
|
@Transactionalpublic class ShoppingCart { ... } |
或者我们可以指定一个方法的事务
|
1
2
3
|
public class ShoppingCart { @Transactional public void checkout() { ... }} |
2.拦截器实现(Implementing interceptors)
我们实际上要实现提供了这种事务管理方面的拦截器,所以我们需要做的是创建一个标准的拦截,并配上@Interceptor和@transactional注解.
|
1
2
3
4
5
6
|
@Transactional @Interceptorpublic class TransactionInterceptor { @AroundInvoke public Object manageTransaction(InvocationContext ctx) throws Exception { ... }} |
拦截器可以利用依赖注入:
|
1
2
3
4
5
6
7
8
|
@Transactional @Interceptorpublic class TransactionInterceptor { @Resource UserTransaction transaction; @AroundInvoke public Object manageTransaction(InvocationContext ctx) throws Exception { ... }} |
多个拦截器可以使用相同的拦截器绑定类型。
@Resource和@Inject的区别:

3.启用拦截器(Enabling interceptors)
默认情况下,所有拦截器被禁用.要使用拦截器.需要在bean.xml中进行配置,以启用.从CDI 1.1起拦截器可以使用@Priority注释为整个应用程序启用。
|
1
2
3
4
5
6
7
8
9
10
|
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"> <interceptors> <class>org.mycompany.myapp.TransactionInterceptor</class> </interceptors></beans> |
这样有2个好处:
- 拦截器比较重要,在XML中确保其确定性行为
- 它让我们在部署时启用或禁用拦截器类。
当然也可以配置启用多个拦截器
|
1
2
3
4
5
6
7
8
9
10
11
|
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://xmlns.jcp.org/xml/ns/javaee http://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:
|
1
2
3
|
@Priority(Interceptor.Priority.LIBRARY_BEFORE+10) @Interceptor public class ValidationInterceptor { ... } |
4.Interceptor bindings with members(拦截器注解属性)
假设我们想要添加一些额外的信息给我们的@transactional注解:
|
1
2
3
4
5
6
7
|
@InterceptorBinding@Target({METHOD, TYPE})@Retention(RUNTIME)public @interface Transactional { boolean requiresNew() default false;} |
下面是requiresNew为true的拦截器
|
1
2
3
4
5
6
|
@Transactional(requiresNew = true) @Interceptorpublic class RequiresNewTransactionInterceptor { @AroundInvoke public Object manageTransaction(InvocationContext ctx) throws Exception { ... }} |
如下使用:
|
1
2
|
@Transactional(requiresNew = true)public class ShoppingCart { ... } |
但是如果我们只有一个拦截器,我们希望容器拦截器绑定时忽略requiresNew的值,也许这些信息只用于拦截器实现。我们可以使用@Nonbinding注释:
|
1
2
3
4
5
6
7
|
@InterceptorBinding@Target({METHOD, TYPE})@Retention(RUNTIME)public @interface Secure { @Nonbinding String[] rolesAllowed() default {};} |
5.Multiple interceptor binding annotations(多重拦截器绑定注解)
通常我们使用拦截器绑定的组合类型绑定多个拦截器bean。例如,下面的声明将用于绑定TransactionInterceptor和SecurityInterceptor这2个拦截器到ShoppingCart.
|
1
2
|
@Secure(rolesAllowed="admin") @Transactionalpublic class ShoppingCart { ... } |
然而,在非常复杂的情况下,一个拦截器本身可能指定拦截器绑定类型:
|
1
2
|
@Transactional @Secure @Interceptorpublic class TransactionalSecureInterceptor { ... } |
那么这个拦截器可以绑定到checkout() 方法,以下任何组合都可使用:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public class ShoppingCart { @Transactional @Secure public void checkout() { ... }}@Securepublic class ShoppingCart { @Transactional public void checkout() { ... }}@Transactionalpublic class ShoppingCart { @Secure public void checkout() { ... }}@Transactional @Securepublic class ShoppingCart { public void checkout() { ... }} |
6. Interceptor binding type inheritance(拦截器绑定类型继承)
Java语言支持注解的一个限制就是缺乏注解继承.注解应该重用内置已有的.就如同下面这段代码表达的意思
|
1
2
|
//实际没这写法public @interface Action extends Transactional, Secure { ... } |
幸运的是,CDI围绕Java没有的这个特性开展了一些工作.
我们会标注一个拦截器绑定类型,其有其他拦截器的绑定类型,(称为元注解)
表述起来有点费劲,就如同下面代码这样.
|
1
2
3
4
5
|
@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规范>.如下:
|
1
2
3
4
5
|
@Interceptors({TransactionInterceptor.class, SecurityInterceptor.class})public class ShoppingCart { public void checkout() { ... }} |
但缺点也很明显,不推荐使用.缺点如下:
- 拦截器在代码中是硬编码.
- 拦截器在部署时不好更改.
- 拦截器命令是非全局的——它是在类级别由拦截器的顺序列出.
因此还是使用上面CDI的使用方式比较好.
CDI services--interceptors(拦截器)的更多相关文章
- (vue.js)axios interceptors 拦截器中添加headers 属性
(vue.js)axios interceptors 拦截器中添加headers 属性:http://www.codes51.com/itwd/4282111.html 问题: (vue.js)axi ...
- flume1.8 Interceptors拦截器(五)
1. Flume Interceptors Flume有能力修改/删除流程中的events.这是在拦截器(interceptor)的帮助下完成的.拦截器(Interceptors)是实现org.apa ...
- springMVC之mvc:interceptors拦截器的用法
1.配置拦截器 在springMVC.xml配置文件增加: <mvc:interceptors> <!-- 日志拦截器 --> <mvc:interceptor> ...
- angular之interceptors拦截器
<!DOCTYPE html> <html ng-app="nickApp"> <head> <meta charset="UT ...
- springMVC <mvc:interceptors>拦截器的使用
首先在springMVC.xml配置如下代码 <!-- 拦截器 --> <mvc:interceptors> <bean class="com.base.Acc ...
- angular http interceptors 拦截器使用分享
拦截器 在开始创建拦截器之前,一定要了解 $q和延期承诺api 出于全局错误处理,身份验证或请求的任何同步或异步预处理或响应的后处理目的,希望能够在将请求移交给服务器之前拦截请求,并在将请求移交给服务 ...
- Interceptors - 拦截器
1.概述 Flume有能力在运行阶段修改/删除Event,这是通过拦截器(Interceptors)来实现的. 拦截器需要实现org.apache.flume.interceptor.Intercep ...
- vue interceptors(拦截器)
拦截器 顾名思义: 就是半路个您劫持, 拦截器 其实在项目和自己写demo中,总会遇到请求方面需要在请求头里面做判断或者添加一些东西, 这时候 vue 中应用中axios的 interceptors ...
- vue拦截器Vue.http.interceptors.push
刚开始学vue,github上down了一个开源项目,看源代码的时候看到了这个地方: /** * @export * @param {any} request * @param {any} next ...
- SpringMVC 文件上传&拦截器&异常处理
文件上传 Spring MVC 为文件上传提供了直接的支持,这种支持是通过即插即用的 MultipartResolver 实现的.Spring 用 Jakarta Commons FileUpload ...
随机推荐
- AtCoder Grand Contest 030 (AGC030) C - Coloring Torus 构造
原文链接https://www.cnblogs.com/zhouzhendong/p/AGC030C.html 题解 才发现当时是被题意杀了. 当时理解的题意是“对于任意的 (i,j) ,颜色 i 和 ...
- 014 链表中倒数第k个结点
1.题目 输入一个链表,输出该链表中倒数第k个结点. 2.思路 Java代码,通过校验.代码思路如下:两个指针,先让第一个指针和第二个指针都指向头结点,然后再让第一个指正走(k-1)步,到达第k个节点 ...
- 我的第二本译作《精通OpenStack》上架啦:书籍介绍和译者序
1. 书籍简介 英文书名:Mastering OpenStack Second Edition 作者:[德] 奥马尔-海德希尔(Omar Khedher)[印] 坚登-杜塔-乔杜里(Chanda Du ...
- Android项目中的config.xml文件 “config.xml”
Android应用程序需要保存一些配置时,可以将这些配置项放置到values/config.xml文件中. 实例分析: <?xml version="1.0" encodin ...
- CSS(三)
CSS盒子模型 盒子模型解释 元素在页面中显示成一个方块,类似一个盒子,CSS盒子模型就是使用现实中盒子来做比喻,帮助我们设置元素对应的样式.盒子模型示意图如下: 把元素叫做盒子,设置对应的样式分别为 ...
- css 绘制三角形
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- js递归遍历多维数组并在修改数组的key后返回新的多维数组
我司最近正在用VUE做一个基于用户权限显示不同左侧菜单的后台管理系统,接口会根据用户的权限不同返回不同的菜单名称.URL等,前端要将这些菜单名称及URL动态添加到系统的左侧,这里就用到了vue-rou ...
- mobile_1 物理像素
1 物理像素 需求: border: 1px solid red; 在移动端 dpr 为 2 的屏幕上,实际上是 2 物理像素. 如何实现 1 物理像素? 首先,肯定不能 border: 0.5 ...
- ajax 传递中文字符参数 问题
使用ajax 传递中文字符串时, 服务端会接收不到预期的 中文字符. 此时,需要对 js中的中文字符参数进行 编码, 到达服务端后, 再为其解码 即可. 前端: var url = '....'; ...
- Java 前端模板引擎学习:thymeleaf 模板引擎
模板引擎接口 ITemplateEngine 一.后台数据与外部数据 1.处理后台数据 $表达式是个变量表达式,用于处理在 request parameters and the request, s ...