SpringBoot下使用拦截器

773 阅读3分钟

这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战

1.拦截器

在前面有篇文章讲到jwt:juejin.cn/post/699360… 在访问一些业务接口必须要进行登录后才能访问,则可以设置一个拦截器对访问的进行统一拦截

  • 拦截器应用场景

    记录日志,权限检查(如:检查是否登录),性能检查(可以记录进入处理器的开始和处理完的结束时间)等

  • springboot拦截器 1.编写拦截器实现类,实现接口HandlerInterceptor,其中有三个方法:

    preHandle:是请求执行前执行的 postHandler: 是请求结束执行的 (每个拦截器都可以对执行进行后处理,按执行链的相反顺序应用)

    afterCompletion: 完成请求处理后的回调,即呈现视图后的回调。将在处理程序执行的任何结果时调用,从而允许进行适当的资源清理。(只有当这个拦截器的preHandle方法成功完成并返回true时才会被调用!)

  • springboot中 注入拦截器 编写拦截器配置文件类并继承  WebMvcConfigurer类

重写方法addInterceptors:添加的拦截器,用于控制器方法调用的预处理和后处理。拦截器可以被注册以应用于所有请求,也可以被限制为URL模式的子集。注意,这里注册的拦截器只应用于控制器,而不适用于资源处理程序请求(拦截的是控制层的请求地址)

2.代码示例

  • 配置springboot拦截器 这里只重写了一个preHandle方法 主要用于登录的拦截请求 ,其中PassToken注解是自定义的注解,若在加上这个注解,则拦截器不进行拦截处理
@Component
public class JwtInterceptor implements HandlerInterceptor  {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");
        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) return  true;   // 如果不是映射到方法直接通过
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        //检查是否有passtoken验证 若有直接跳过认证
        if (method.isAnnotationPresent(PassToken.class)){
            PassToken annotation = method.getAnnotation(PassToken.class);
            if (annotation != null) return true;
        }
        if (token == null) throw new UserException("无token 请重新登陆");
        //验证token
        JwtUtil.verifyToken(token);
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }
}

//自定义注解
```
/**
 * 加上这个注解可以不用进行token验证
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
}
```
  • 拦截器的注入 重写addInterceptors方法,增加了一个拦截器new JwtInterceptor(),并增加了拦截器路径(这里对所有路径都进行了拦截,这个可以根据实际情况进行配置)
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JwtInterceptor())
                .addPathPatterns("/**");
    }
}

示例代码:

@PostMapping(value ="/testToken",produces = "application/json; charset=UTF-8")
public String testToken(HttpServletRequest request){
    return "您已通过验证";
}

image.png


@PostMapping(value ="/testToken1",produces = "application/json; charset=UTF-8")
@PassToken
public String testToken1(HttpServletRequest request){
    return "不用进行拦截器拦截";
}

image.png

  • 目前对过滤器,拦截器,切片三者的认识和理解并不够深入,但三者比较明显的区别是: 三者拦截的顺序以及范围是不一样的,可以参考下面这张表(对于@ControllerAdvice一般是去拦截处理控制器抛 出的异常 可以查看这篇文章:juejin.cn/post/699163…
过滤器拦截器Aspect
范围所有web请求部分web请求偏向于业务层面的拦截
实现原理函数回调JAVA反射机制动态代理
是否依赖servlet容器
servlet提供的支持Filter接口
作用级别系统级非系统级皆可
servlet提供的支持Filter接口
spring提供的支持HandlerInterceptorAdapter类 HandlerInterceptor接口@Aspect
需要重写的方法doFilterpreHandle、postHandle、afterCompletionBefore、After、Around

image.png