首页 > 其他分享 >前端工作小结1-拦截器的使用

前端工作小结1-拦截器的使用

时间:2023-05-18 11:32:28浏览次数:40  
标签:... 拦截器 Transactional 前端 绑定 class 小结 public


1.拦截器综述

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

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

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

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

EJB超时时使用的拦截器

 

public class TimeoutInterceptor {
      
        @AroundTimeout
        public Object manageTransaction(InvocationContext ctx) throws Exception { ... }
     }在业务上,对某一个Bean的方法进行拦截
    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封装了客户端所调用业务方法的一些信息。

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 {
         @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我们要申明.
首先定义一个注解

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

@Transactional public class ShoppingCart { ... } 或者我们可以指定一个方法的事务
    public class ShoppingCart {
        @Transactional public void checkout() { ... }
     }    1
     2
     3

2.拦截器实现(Implementing interceptors)

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

@Transactional @Interceptor
     public class TransactionInterceptor {
      
        @AroundInvoke
        public Object manageTransaction(InvocationContext ctx) throws Exception { ... }
     }拦截器可以利用依赖注入:
    @Transactional @Interceptor
     public class TransactionInterceptor {
      
         @Resource UserTransaction transaction;
      
         @AroundInvoke
         public Object manageTransaction(InvocationContext ctx) throws Exception { ... }
     }

多个拦截器可以使用相同的拦截器绑定类型。
@Resource和@Inject的区别:
3.启用拦截器(Enabling interceptors)

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

<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中确保其确定性行为
它让我们在部署时启用或禁用拦截器类。
当然也可以配置启用多个拦截器

<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:

    @Priority(Interceptor.Priority.LIBRARY_BEFORE+10)
     @Interceptor
     public 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 {
      
        @AroundInvoke
        public 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 { ... }

    1
    2

那么这个拦截器可以绑定到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 { ... }    1
     2

幸运的是,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的使用方式比较好.
 

标签:...,拦截器,Transactional,前端,绑定,class,小结,public
From: https://blog.51cto.com/u_15460007/6296160

相关文章

  • flask_前端继承
      外部引入一段代码,include    ......
  • 前端-Vue语法使用
    ES6做为动态语言,感觉底层开始-基本类型就全引用。做为实例化的变量,也变得像指向指针的指针,可以随时切换指针,从而最终的数据类型也更着切换总的来说概念上会比较别扭。以及灵活导致的不确定性。底层都是对象,从对象的类型来搭建。基本类型\ PrimitivevalueUndefined,Null,Boo......
  • 最近遇到的一个问题 后端写好的接口,前端怎么获取数据
    这是我后端的接口:GET接口这是我前端运行的项目地址:简单使用:咱门前端使用颇受好评的axios来发起请求这是它的官网:https://www.axios-http.cn/不过要在vue中使用它,就需要先安装打开终端输入一下命令 npminstallaxios然后在需要使用的页面<script>中标签引入a......
  • Nginx 常用的基础配置(web前端相关方面)
    基础配置userroot;worker_processes1;events{worker_connections10240;}http{log_format'$remote_addr-$remote_user[$time_local]''"$request"$st......
  • 前端-VUE
    工程化这里要从node.js开始。node.js要弄一个基于事件驱动、非阻塞I/O的的web服务,发现V8引擎+JavaScript很合适。这样Js就能直接写后端应用。然后发展成作为本地的运行容器(类似jdk),将js导入到了本地运行领域。以此位基础,发展出了生态环境,里面关系挺绕的,各种轮子,互相占位。......
  • VUE前端随笔计2
    又是小白记录问题的一次,老规矩,还是抄别人的代码来改。 在表标签中找到了一个点击事件定位代码,对比别人的,发现自己的删多了,把这个补充回去就行了,具体意思不太明白,大概是给这个模型里面填充这行数据。 ......
  • 简单聊两句前端模块化
    在前端开发中,模块化是一种将代码拆分为独立模块的开发方法。它通过将功能相似或相关的代码组织成可复用、可维护的模块,以提高开发效率和代码质量。模块化的主要目的是解决传统的JS开发存在的问题,例如全局命名冲突、代码复用困难、依赖管理混乱等。通过模块化,可以将代码拆分为独立......
  • SpringBoot拦截器
    在项目的开发中,在某些情况下,我们需要对客户端发出的请求进行拦截,常用的API拦截方式有Fliter,Interceptor,ControllerAdvice以及Aspect。 上面的图是Spring中拦截机制,请求从Filter-->>Controller的过程中,只要在指定的环节出现异常,可以通过对应的机制进行处理。反之在任何一个环节......
  • 服务器 nginx 前端配置 SSL 证书并能访问 HTTPS
    安装以下步骤,按图索骥即可。 首先,没安装nginx的去这个地址,安装nginx。本人版本是(1.18.0).https://nginx.org/安装好了之后,在nginx目录下执行cmd运行命令nginx.exe-V出现以下情况就证明nginx自带了SSL模块了,不需要额外安装 有了上面这个东西之后,nginx底下......
  • 学习Web前端有什么好方法吗?
    很多人想要学习Web前端,但是又不知道从何入手。事实上,想要学好Web前端,掌握正确的学习方法很重要。为大家具体讲解一下,学习Web前端需要掌握的学习方法有哪些。 一、了解什么是Web前端 所谓“知己知彼,百战不殆”,在学习Web前端之前,首先应该了解什么是Web前端。所有的用户终端产品与视......