• 在springboot中使用拦截器


    目前有一个需求,是在现有项目中集成一个简单的登录功能,想到了使用过滤器和拦截器实现,这篇文章介绍如何使用spring的拦截器。

    1 拦截器(Interceptor)定义

    拦截器是在面向切面编程中应用的,就是在你的service或者一个方法前调用一个方法,或者在方法后调用一个方法。是基于JAVA的反射机制。

    1.1 拦截器(Interceptor)执行顺序

    1. 请求到达 DispatcherServlet
    2. DispatcherServlet 发送至 Interceptor ,执行 preHandle
    3. 请求达到 Controller
    4. 请求结束后,postHandle 执行

    1.2 拦截器(Interceptor)和过滤器(Filter)的执行顺序

    过滤前->拦截前->Action处理->拦截后->过滤后
    在这里插入图片描述

    1.3 方法介绍

    1)预处理preHandle()方法

    用户发送请求时,先执行preHandle()方法。会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则执行用户请求的url方法。

    2)后处理postHandle()方法

    调用了Service并返回ModelAndView,但未进行页面渲染,可以在这里继续修改ModelAndView或者返回值

    3)返回处理afterCompletion()方法

    已经渲染了页面,在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。

    注:一般使用preHandle这个拦截器进行预处理,对url进行请求拦截

    2 Spring Boot使用拦截器

    2.1 自定义拦截器

    需要继承HandlerInterceptorAdapter类
    注意,在更高版本中HandlerInterceptorAdapter已经弃用,推荐实现HandlerInterceptor接口

    @Slf4j
    @Component
    public class LoginInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.info("进入到拦截器中:preHandle() 方法");
            System.out.println(request.getServletPath());
            return true;
        }
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.info("进入到拦截器中:postHandle() 方法中");
            System.out.println(request.getRequestURI());
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            log.info("进入到拦截器中:afterCompletion() 方法中");
            System.out.println(request.getServletPath());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    2.2 注册拦截器

    需要继承WebMvcConfigurerAdapter类
    注意,在更高版本中WebMvcConfigurerAdapter已经弃用,推荐实现WebMvcConfigurer接口
    需要重写addInterceptors方法,这里是对根目录"/"进行拦截,可以指定拦截url请求目录

    @Configuration
    public class InterceptorAdapterConfig  implements WebMvcConfigurer {
    
        private final LoginInterceptor loginInterceptor;
    
        public InterceptorAdapterConfig(LoginInterceptor loginInterceptor) {
            this.loginInterceptor = loginInterceptor;
        }
    
        @Override
        public void addInterceptors(InterceptorRegistry registry)
        {
            //注册自己的拦截器并设置拦截的请求路径
            registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3 对指定方法进行拦截

    这里的注册监听器,自定义监听器写法和前面一致。

    如果对url目录下所有的请求进行了监听,但需要对某些请求方法不进行拦截或单独拦截,可以采用自定义注解方式,对方法加上自定义注解,拦截器进行扫描,对出现过自定义注解的方法进行单独处理

    3.1 编写一个注解

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface NeedLogin {
        boolean LoginSuccess() default true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.2 修改拦截器

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("进入到拦截器中:preHandle() 方法");
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        NeedLogin loginVerify = handlerMethod.getMethodAnnotation(NeedLogin.class);
        if (loginVerify == null) {
            log.info("不需要对该路径 进行拦截");
            return true;
        }else {
            log.info("对该路径 进行拦截");
            log.info("业务操作...");
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.3 编写controller测试

    @GetMapping("/test")
    @NeedLogin
    public String test() {
        System.out.println(LocalDateTime.now());
        return LocalDateTime.now().toString();
    }
    
    @GetMapping("/test2")
    public String test2() {
        System.out.println(LocalDateTime.now());
        return LocalDateTime.now().toString();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    35岁左右的项目经理,这5种能力一定要有​
    Biotin hydrazide HCl|CAS:66640-86-6|生物素-酰肼盐酸盐
    Python之Excel数据相关
    Django路由层和视图层
    VueUI Day01(7.29)Vue 组件库、Vue 组件库、NavMenu 组件、ElementUI 的布局相关组件
    setup中的nextTick函数
    Cypress 踩坑记 - DOM 遮挡
    机器人控制算法八之路径规划算法:RRT、RRT-Connect、Dynamic-Domain RRTs*
    聊一下Glove
    网页制作基础大三dw作业 基于HTML+CSS+JavaScript新能源汽车租赁(6个页面)
  • 原文地址:https://blog.csdn.net/weixin_43702146/article/details/125543246