Spring Boot 拦截器的使用

一、使用场景

比如对特定的URL检查用户是否登录,打印处理用户请求耗时的时间等,可以用拦截器来实现。


二、拦截器使用

定义拦截器,需要实现 HandlerInterceptor 接口,接口中有3个方法

  • preHandle:在DispatcherServlet处理请求执行之前被调用
  • postHandle:在DispatcherServlet处理请求执行完成后,生成视图之前被调用(还未渲染页面)
  • afterCompletion:在DispatcherServlet处理请求执行完成后,且已生成视图被调用,可以用于清除资源(已渲染了页面)

)2.1 创建自定义拦截器 MyInterceptor  类

@Slf4j
public class MyInterceptor implements HandlerInterceptor {

    /**
     * 定义拦截器:需要实现 HandlerInterceptor 接口
     *
     * HandlerInterceptor接口中有3个方法
     * 1.preHandle:在业务处理器处理请求之前被调用
     * 2.postHandle:在业务处理器处理请求执行完成后,生成视图之前执行(还未渲染页面))
     * 3.afterCompletion:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面)
     */

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        String methodName = method.getName();
        log.info("===拦截到了方法:{},在该方法执行之前执行===", methodName);

        // 判断用户有没有登陆,一般登陆后的用户都有一个对应的token
        String token = request.getParameter("token");
        if (StringUtils.isEmpty(token)) {
            log.info("用户没有登陆,没有执行权限......请登陆");
            return false;
        }

        // 通过方法,可以获取该方法上的自定义注解,然后通过注解来判断该方法是否要被拦截
        // @UnInterceptor 自定义注解,不被拦截
        UnInterceptor unInterceptor = method.getAnnotation(UnInterceptor.class);
        if (null == unInterceptor) {
            return false;
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("执行完方法之后进行(Controller方法调用之后),但是此时还没有进行视图渲染");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("整个请求都处理完毕,DispatcherServlet也渲染了对应的视图,此时可以做一些清理的工作等等");
    }
}

)2.2 创建拦截器配置类,实现 WebMvcConfigurer 接口,对所有请求由 MyInterceptor 类进行拦截

@Configuration
public class MyInterceptorConfig implements WebMvcConfigurer {

    /**
     * 解决静态资源被拦截问题
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 实现WebMvcConfigurer不会导致静态资源被拦截
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
    }
}

)2.3 创建controller类,接收请求

@Controller
@RequestMapping("/interceptor")
public class InterceptorController {

    @GetMapping("/test")
    public String test() {
        return "hello";
    }

    @UnInterceptor
    @GetMapping("/test1")
    @ResponseBody
    public String test1() {
        return "不被拦截";
    }
}

)2.4 创建 hello.html 页面,用于页面返回渲染


三、测试

)3.1 对于 token 校验测试。在 MyInterceptor 类中的 preHandle 方法中注释 @UnInterceptor 校验的代码,

 访问 localhost:8080/interceptor/test 时,会被拦截,由于没有带token值,执行 preHandle 方法时返回false,不会继续往下执行

 通过 postman 表单请求设置 token 值,再次请求

测试结果如下,可以看到 MyInterceptor 类中,三个方法都已执行,且返回了 hello.html 中的页面

)3.2 对于自定义注解校验测试。在 MyInterceptor 类中的 preHandle 方法中注释token校验的代码,放开 @UnInterceptor 的校验代码,

访问 localhost:8080/interceptor/test1 可以看到 MyInterceptor 类中,三个方法都已执行

原文地址:https://www.cnblogs.com/lwcode6/p/13450712.html