zoukankan      html  css  js  c++  java
  • 【springboot】过滤器、监听器、拦截器,Aspect切片

    转自:

      https://blog.csdn.net/cp026la/article/details/86501019

    简介:

      本章介绍拦截器、过滤器、切片对请求拦截的使用与区别,以及监听器在 springboot1.5 中的简单使用

    过滤器、拦截器、切片拦截请求的对比:

    相同点: 都可以对请求进行拦截。
    不同点:
    1、过滤器对请求的拦截只能获取到原始的Request 和 Response 的信息。
    2、拦截器对请求的拦截可以获取原始的Request、Response和所有的controller及方法名,但无法获取方法的参数信息。
    3、Aspect切片只能获取方法的参数,原始的Request、Response不能获取。

    所以,实际项目需根据需求选择使用何种方式拦截请求。

    一、过滤器:

    1、实现Filter接口

    /**
     * @Auther: xf
     * @Date: 2018/11/19 19:30
     * @Description: 自定义过滤器
     *
     * Filter 只能获取request 和 response 并不知道请求是哪个 controller 处理的
     */
    @Slf4j
    public class CustomFilter implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            log.info("过滤器初始化>>>>>>>");
        }
    
        /**
         * 请求被拦截的时候进行调用
         */
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            log.info(">>>>>>>>>>>>过滤器拦截请求处理逻辑>>>>>>>>>>>>>");
    
            // 业务逻辑
            long startTime = System.currentTimeMillis();
    
            // 过滤器链,给下一个过滤器
            filterChain.doFilter(servletRequest, servletResponse);
            log.info("请求时间:" + (System.currentTimeMillis() - startTime));
        }
    
        @Override
        public void destroy() {
            log.info("过滤器销毁>>>>>>>");
        }
    }  

    2、过滤器配置类:

    传统的web项目中,过滤器的配置是在web.xml中添加。SpringBoot需要使用FilterRegistrationBean来完成配置。

    /**
     * @Auther: xf
     * @Date: 2018/11/19 19:58
     * @Description:  传统的项目配置 Filter 在 web.xml 中添加
     * 在Spring boot中,我们需要 FilterRegistrationBean 来完成配置
     */
    @Configuration
    public class CustomFilterConfig {
        @Bean
        public FilterRegistrationBean customFilter() {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setFilter(new CustomFilter());
            registration.addUrlPatterns("/*");
            registration.setName("customFilter");
            registration.setOrder(1);
            return registration;
        }
    }  


    3、启动项目,随便请求一个接口测试效果:

    控制台有拦截器的日志。

    4、配置过滤器的方式二:

    直接通过@WebFilter注解配置(注释掉上面的CustomFilterConfig配置类)

    @Slf4j
    // 多个过滤器,使用此注解指定执行顺序,越小越先执行
    @Order(1)
    // 在 CustomFilterConfig 中配置  注释掉 @WebFilter
    @WebFilter(urlPatterns = "/*", filterName = "customFilter")
    public class CustomFilter implements Filter {
        ...
    }  

    注意:
    @WebFilter 是Servlet3.0 的规范,并不是SpringBoot提供的,需加上@ServletComponentScan注解扫描指定的包。我们这里加到启动类上。

    // filter和servlet、listener之类的需要单独进行注册才能使用,spring boot里面提供了该注解起到注册作用
    @ServletComponentScan
    // mapper 接口类扫描包配置
    @MapperScan("com.coolron.*.dao")
    @SpringBootApplication(scanBasePackages = "com.coolron")
    public class SpringbootApplication {
        ...
    }  


    二、拦截器:

    1、自定义拦截器1:

    @Slf4j
    public class MyInterceptor1 implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)  throws Exception {
            log.info(">>>MyInterceptor1>>>>>>>在请求处理之前进行调用(Controller方法调用之前)");
            return true;// 只有返回true才会继续向下执行,返回false取消当前请求
        }
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                               ModelAndView modelAndView) throws Exception {
            log.info(">>>MyInterceptor1>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");
        }
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
            log.info(">>>MyInterceptor1>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)");
        }
    }  

    2、自定义拦截器2:

    /**
     * 自定义拦截器2
     */
    @Slf4j
    public class MyInterceptor2 implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            log.info(">>>MyInterceptor2>>>>>>>在请求处理之前进行调用(Controller方法调用之前)");
            return true;// 只有返回true才会继续向下执行,返回false取消当前请求
        }
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                               ModelAndView modelAndView) throws Exception {
            log.info(">>>MyInterceptor2>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");
        }
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
            log.info(">>>MyInterceptor2>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)");
        }
    }

    3、拦截器配置类:

    /**
     * @Auther: xf
     * @Date: 2018/11/19 21:09
     * @Description:
     */
    @Configuration
    public class InterceptorConfig extends WebMvcConfigurerAdapter {
        /*
         * 拦截器配置
         * 在spring-mvc.xml配置文件内添加<mvc:interceptor>标签配置拦截器。
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
    
            // 多个拦截器组成一个拦截器链
            // addPathPatterns 用于添加拦截规则
            // excludePathPatterns 用户排除拦截
             registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**").excludePathPatterns("/login");
             registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**");
            // 父类的配置
            super.addInterceptors(registry);
        }
    }  

    三、Aspect切片拦截:

    1、自定义切片:

    /**
     * @Description:  
     * 可以拿到请求的具体controller 对应的方法的具体参数值  但是拿不到 原始的request 和 response
     *
     * 切入点(注解):
     * 1、 在哪些方法上起作用
     * 2、 什么时候起作用
     *
     * 增强(方法)
     * 1、起作用是执行的业务逻辑
     */
    // 声明切片类
    @Slf4j
    @Aspect
    @Component
    public class CustomAspect {
    
        // 在什么时候起作用
        // @Before() 相当于拦截器的 PreHandle() 方法
        // @After()  拦截的方法响应之后执行
        // @AfterThrowing 方法抛出某些异常的时候调用
        // @Around 环绕 覆盖前面三种
        // 环绕的方式调用下面的方法
        @Around("execution(* com.coolron.*.controller..*.*(..))")
        // ProceedingJoinPoint 类 包含了当前拦截的方法的一些信息
        public Object method(ProceedingJoinPoint pjp) throws Throwable {
            log.info("=====Aspect处理=======");
            Object[] args = pjp.getArgs();
            for (Object arg : args) {
                log.info("参数为:" + arg);
            }
            long start = System.currentTimeMillis();
            // 相当于Filter 的 chain.doFilter()  调用被拦截的那个方法  返回值 object 与 controller中方法的返回值相同
            Object object = pjp.proceed();
            log.info("Aspect 耗时:" + (System.currentTimeMillis() - start));
            return object;
        }
    }  

    execution表达式参看SpringBoot>07 - 事物处理。

    2、启动访问任意接口:

    观察控制台发现Filter、Interceptor、切片执行顺序:

    拦截顺序 : Filter >>> Interceptor >>> Aspect >>> controller
    若果有异常返回结果: controller >>> Aspect >>> ControllerAdvice(全局异常处理类上) >>> Interceptor >>> Filter

    四、监听器:

    1、自定义监听器,实现ServletRequestListener接口

    /**
     * @Auther: xf
     * @Date: 2018/11/19 21:42
     * @Description:  监听器
     */
    @Slf4j
    @WebListener
    public class RequestListener implements ServletRequestListener {
        @Override
        public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
            log.info("监听器销毁>>>>>");
        }
    
        @Override
        public void requestInitialized(ServletRequestEvent servletRequestEvent) {
            log.info("监听器初始化>>>>>");
        }
    } 

    2、测试:随便请求一个接口会看到监听器初始化和销毁的日志。

    注意:案例中实现的是request的监听器。用于监听request对象的创建、销毁。
    常见的监听器:
    1、HttpSessionListener:监听session对象的创建、销毁
    2、ServletRequestListener:监听request对象的创建、销毁
    3、ServletContextListener:监听servletContext对象的创建、销毁

  • 相关阅读:
    Key Figure、Exception Aggreagion、Non-Cumulative KeyFigure
    特征创建:Reference Characteristic、Template
    Compounding绑定属性
    特征的SID表、M表、P表、Q表、X表、Y表、T表
    特征的Attribute Only选项
    将InfoObject作为信息提供者Characteristic is InfoProvider
    滚动RollUp、压缩
    Aggregation 聚集
    VirtualProvider (VirtualCube)虚拟立方体
    自建数据源(RSO2)、及数据源增强
  • 原文地址:https://www.cnblogs.com/wjqhuaxia/p/12148842.html
Copyright © 2011-2022 走看看