zoukankan      html  css  js  c++  java
  • SpringBoot 2.x (7):拦截器

     类似以前SpringMVC的拦截器,但也有一些区别

    SpringBoot的拦截器有两种方式:

    第一种方式:过时的方式,适用于SpringBoot1.x的方式

    package org.dreamtech.springboot.interceptor;
    
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    @SuppressWarnings("deprecation")
    public class CustomWebMvcConfigurer extends WebMvcConfigurerAdapter {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/test/*/**");
            super.addInterceptors(registry);
        }
    }

    第二种方式:基于Java8与Spring5的方式

    原理:在WebMvcConfigurer接口中定义了默认方法,利用Java8新特性:接口中可以写方法

    package org.dreamtech.springboot.interceptor;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    public class CustomWebMvcConfigurer implements WebMvcConfigurer {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/login/*/**");
            WebMvcConfigurer.super.addInterceptors(registry);
        }
    }

    LoginInterceptor:只是实现了三个基本方法,分别打印一句话,了解执行顺序:

    package org.dreamtech.springboot.interceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    public class LoginInterceptor implements HandlerInterceptor {
        /**
         * 拦截之前调用(进入Controller之前)
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            System.out.println("[ preHandle LoginInterceptor ]");
            return HandlerInterceptor.super.preHandle(request, response, handler);
        }
    
        /**
         * 调用方法之后,视图渲染之前
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                ModelAndView modelAndView) throws Exception {
            System.out.println("[ postHandle LoginInterceptor ]");
            HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
        }
    
        /**
         * 完成拦截之后,用于清理资源
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
            System.out.println("[ afterCompletion LoginInterceptor ]");
            HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
        }
    }

    Controller:

    package org.dreamtech.springboot.controller;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class DemoController {
    
        @RequestMapping("/login/account")
        private Object account() {
            Map<String, Object> modelMap = new HashMap<String, Object>();
            modelMap.put("money", 1000);
            System.out.println("[ account DemoController ]");
            return modelMap;
        }
    }

    访问localhost:8080/login/account打印情况如下:

    [ preHandle LoginInterceptor ]
    [ account DemoController ]
    [ postHandle LoginInterceptor ]
    [ afterCompletion LoginInterceptor ]

    如果没有以上打印,要注意这几点:

    1.是否有@Configuration注解

    2.是否将拦截路径写成/xxx/*/**,如果是/xxx/*/*就会拦截失败

    同样地,我们可以添加多个拦截器

            registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/login/*/**");
            registry.addInterceptor(new TestInterceptor()).addPathPatterns("/test/*/**");
            registry.addInterceptor(new DemoInterceptor()).addPathPatterns("/demo/*/**");

    或者链式调用:拦截所有路径,但不包括/login

    registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/login");

    多个拦截器的调用顺序:可以理解为包裹的方式

    package org.dreamtech.springboot.interceptor;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    public class CustomWebMvcConfigurer implements WebMvcConfigurer {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/login/*/**");
            registry.addInterceptor(new DemoInterceptor()).addPathPatterns("/login/*/**");
            WebMvcConfigurer.super.addInterceptors(registry);
        }
    }

    DemoInterceptor和LoginInterceptor内容基本一致

    最终的打印:

    [ preHandle LoginInterceptor ]
    [ preHandle DemoInterceptor ]
    [ account DemoController ]
    [ postHandle DemoInterceptor ]
    [ postHandle LoginInterceptor ]
    [ afterCompletion DemoInterceptor ]
    [ afterCompletion LoginInterceptor ]

    最后:

    Filter和Interceptor的区别:

    1.Filter基于Servlet,而Interceptor不依赖于Servlet容器

    2.Filter只在容器被初始化的时候被调用一次,Interceptor次数没有限制

    3.Interceptor基于AOP思想,Filter基于doFilter方法

    两者的执行顺序:

    过滤前->拦截前->Controller->拦截后->过滤后

  • 相关阅读:
    CCCC练习即感
    1003 我能通过
    录制开讲啦杂感
    OOP第三次上机
    关于C++随机函数
    蓝桥杯杂感。
    CF502C The Phone Number
    It's a secret
    2017-06-22
    2017-05-12
  • 原文地址:https://www.cnblogs.com/xuyiqing/p/10824902.html
Copyright © 2011-2022 走看看