这是我参与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 "您已通过验证";
}
复制代码
@PostMapping(value ="/testToken1",produces = "application/json; charset=UTF-8")
@PassToken
public String testToken1(HttpServletRequest request){
return "不用进行拦截器拦截";
}
复制代码
- 目前对过滤器,拦截器,切片三者的认识和理解并不够深入,但三者比较明显的区别是:
三者拦截的顺序以及范围是不一样的,可以参考下面这张表(对于@ControllerAdvice一般是去拦截处理控制器抛
出的异常 可以查看这篇文章:juejin.cn/post/699163… )
过滤器 | 拦截器 | Aspect | |
---|---|---|---|
范围 | 所有web请求 | 部分web请求 | 偏向于业务层面的拦截 |
实现原理 | 函数回调 | JAVA反射机制 | 动态代理 |
是否依赖servlet容器 | 是 | 否 | 否 |
servlet提供的支持 | Filter接口 | 无 | 无 |
作用级别 | 系统级 | 非系统级 | 皆可 |
servlet提供的支持 | Filter接口 | 无 | 无 |
spring提供的支持 | 无 | HandlerInterceptorAdapter类 HandlerInterceptor接口 | @Aspect |
需要重写的方法 | doFilter | preHandle、postHandle、afterCompletion | Before、After、Around |