详解拦截器

1.什么是拦截器?

Spring MVC中的拦截器(Interceptor)类似于ServLet中的过滤器(Filter),它主要用于拦截用户请求并作出相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。

2.工作原理和工作流程:

一个拦截器,只有preHandle方法返回truepostHandleafterCompletion才有可能被执行;如果preHandle方法返回false,则该拦截器的postHandleafterCompletion必然不会被执行。拦截器不是Filter,却实现了Filter的功能,其原理在于:

  • 所有的拦截器(Interceptor)和处理器(Handler)都注册在HandlerMapping中。
  • Spring MVC中所有的请求都是由DispatcherServlet分发的。
  • 当请求进入DispatcherServlet.doDispatch()时候,首先会得到处理该请求的Handler(即Controller中对应的方法)以及所有拦截该请求的拦截器。拦截器就是在这里被调用开始工作的。

image.png

3.应用场景:

拦截器本质上是面向切面编程(AOP),符合横切关注点的功能都可以放在拦截器中来实现,主要的应用场景包括:

  • 登录验证,判断用户是否登录。
  • 权限验证,判断用户是否有权限访问资源,如校验token
  • 日志记录,记录请求操作日志(用户ip,访问时间等),以便统计请求访问量。
  • 处理cookie、本地化、国际化、主题等。
  • 性能监控,监控请求处理时长等。

4.如何自定义一个拦截器?

自定义一个拦截器非常简单,只需要实现HandlerInterceptor这个接口即可,该接口有三个可以实现的方法,如下:

  • preHandle()方法:该方法会在控制方法前执行,其返回值表示是否知道如何写一个接口。中断后续操作。当其返回值为true时,表示继续向下执行;当其返回值为false时,会中断后续的所有操作(包括调用下一个拦截器和控制器类中的方法执行等 )
  • postHandle()方法: 该方法会在控制器方法调用之后,且解析视图之前执行。可以通过此方法对请求域中的模型和视图作出进一步的修改。
  • afterCompletion()方法:该方法会在整个请求完成,即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。

5.如何使其在Spring Boot中生效:

其实想要在Spring Boot生效其实很简单,只需要定义一个配置类,实现WebMvcConfigurer这个接口,并且实现其中的addInterceptiors()方法即可,代码演示如下:

**

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Autowired
    private  XXX xxx;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //不需要拦截的url
        final  String[] commonExclude={};
        registry.addInterceptor(xxx).excludePathPatterns(commonExclude)
    }
}

6.具体场景举例:

编写拦截器JwtTokenUserInterceptor: 统一拦截用户端发送的请求并进行jwt校验

image.png

/**
 * 定义jwt令牌校验的拦截器
 */
@Component
@Slf4j
public class JwtTokenUserInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 用户端校验jwt
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    //用于处理HTTP请求的预处理。它的作用是验证请求头中的令牌(Token),并根据验证结果决定是否放行请求。
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       
		 //在Spring框架中,HandlerMethod是一个接口,用于处理HTTP请求。当拦截到一个请求时,会将请求对象传递给handler方法进行处理。如果传入的handler对象不是HandlerMethod类型,说明它不是一个处理HTTP请求的方法,因此可以直接放行,不进行后续的处理
        if (!(handler instanceof HandlerMethod)) {            
            return true;
        }
        
        //1、从请求头中获取令牌
        String token = request.getHeader(jwtProperties.getUserTokenName());

        //2、校验令牌
        try {
            log.info("jwt校验:{}", tokeempn);
            //传入管理员密匙和令牌解析令牌,获取其中的声明信息。
            Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
            //从Claims对象中获取员工ID(uId)
            Long uId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
            log.info("当前员工id:", uId);
            /将用户id存储到ThreadLocal
            BaseContext.setCurrentId(uId);
            //3、通过,放行
            return true;
        } catch (Exception ex) {
            //4、不通过,响应401状态码
            response.setStatus(401);
            return false;
        }
    }
}

在WebMvcConfiguration配置类中注册拦截器:

@Configuration
@Slf4j
public class WebMvcConfiguration implements WebMvcConfigurer {
    @Autowired
    private JwtTokenUserInterceptor jwtTokenUserInterceptor;
	/**
     * 注册自定义拦截器
     * @param registry
     */
    protected void addInterceptors(InterceptorRegistry registry) {
        log.info("开始注册自定义拦截器...");      
		//将自定义拦截器jwtTokenUserInterceptor添加到拦截器注册表中。
        registry.addInterceptor(jwtTokenUserInterceptor)
                .addPathPatterns("/user/**")//指定拦截器应用于以"/user/"开头的所有路径
                .excludePathPatterns("/user/user/login")//指定拦截器不应用于路径"/user/user/login"。
                .excludePathPatterns("/user/shop/status");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值