HandlerInterceptor拦截器的原理

是什么

HandlerInterceptor拦截的是请求,是springMVC项目中的拦截器,它拦截的目标是请求的地址。也就是说,它可以对请求进行拦截处理,所有实现了HandlerInterceptor,并且进行了配置的的类,都有这个能力,它的原理,和Filter很相似,我们一起来看一下具体代码是怎么回事。

来个例子

首先我们自己建一个springboot的项目,然后写两个测试接口:

@RequestMapping()
@Controller
@ResponseBody
public class TestController {

    @GetMapping("/test")
    public void test(){
        System.out.println("test");
    }


    @GetMapping("/login/test")
    public void login(){
        TestController.class.getClassLoader();
        System.out.println("login test");
       
    }

然后再写两个拦截器:

public class UserIntercepter implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler)
            throws Exception {
        System.out.println("MyInterceptor 拦截器执行preHandle()方法");
        return true;
    }

    // 当preHandle方法返回值为true的时候才会执行。
    // 重写postHandle方法,在请求完成后执行。
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle执行了");
    }

    // 当preHandle方法返回值为true的时候才会执行。
    // 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面);
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion执行了");
    }
}

第二个:

public class LoginIntercepter implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler)
            throws Exception {
        System.out.println("LoginIntercepter 拦截器执行preHandle()方法");
        return true;
    }

    // 当preHandle方法返回值为true的时候才会执行。
    // 重写postHandle方法,在请求完成后执行。
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("LoginIntercepter的postHandle执行了");
    }

    // 当preHandle方法返回值为true的时候才会执行。
    // 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面);
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("LoginIntercepter的afterCompletion执行了");
    }
}

拦截器写好了,还需要写一个配置类把拦截器配置上才可以起效

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new UserIntercepter())
                .addPathPatterns("/**") ;  //拦截所有的路径

        registry.addInterceptor(new LoginIntercepter())
                .addPathPatterns("/login/**");
    }
}

什么时候加载的

一般来说,我们的类想要被spring容器管理,需要给类加上@Service,@Componet之类的注解,但是很明显,我们的两个拦截器是没有加的,但是我们的配置类加了,所以我们给配置类打个断点,然后启动项目,看看发生了什么。
断点停下来之后,往上找,看看是哪里在调用:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意这是倒着网上找的,所以,很明显,在程序启动的时候,我们自己写的拦截器就被spring的容器管理起来了。

什么时候起效的

那么这玩意儿咋起效呢?这就得看一下我们的org.springframework.web.servlet.DispatcherServlet中的doDispatch(HttpServletRequest request, HttpServletResponse response)方法。

调用接口-找到拦截器

首先我们调用一下test接口,然后看一下org.springframework.web.servlet.DispatcherServlet中的doDispatch(HttpServletRequest request, HttpServletResponse response)断点,可以看到,走到这一步的时候,其实拦截器已经被找到了,我们有两个拦截器,这里加载了全部拦截的那一个。
在这里插入图片描述
然后我们进入getHandler(HttpServletRequest request)看看是怎么找到这个拦截器的。
可以看到,拦截器都保存在这个handlerMappings中的RequestMappingHandlerMapping中,然后mapping.getHandler(request)就负责找到接口对应的servlet和interceptors。
在这里插入图片描述
这个handlerMappings会在有第一次接口调用的时候被初始化,代码在这里:

在这里插入图片描述
看一下具体是怎么拿的:
在这里插入图片描述
注意一下,这里并不需要从头初始化,知识根据类型,从ApplicationContext,也就是容器里请求拿出来就可以。

调用接口-拦截器起效

现在我们已经有了对应的servlet和interceptors,那它如何起效呢,先来整体看一下:
在这里插入图片描述

依次执行各个拦截器的preHandle
在这里插入图片描述
其他的也大致相同。

总结

大致流程总结一下就是,我们编写的拦截器,会通过我们的配置类,被spring的容器管理起来,也就是程序启动时就被加载到容器中,然后当我们需要使用的时候,DispatchServlet初始化的时候,拦截器会被加载到它的属性private List<HandlerMapping> handlerMappings;中,注意,这是个list,我们的接口和拦截器都只属于其中的一个,就是RequestMappingHandlerMapping这个属性,找到对应的处理器之后,就按照流程执行了
以上,其实就HandlerInterceptor

参考

DispatcherServlet浅析

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring 拦截是一种在 Spring MVC 请求处理过程中进行拦截的组件,它可以在请求到达控制前或者返回响应前拦截请求并进行一些处理。拦截可以被用来实现一些通用的功能,比如日志记录、权限控制、性能监控等等。 在 Spring MVC 中,拦截是通过实现 HandlerInterceptor 接口来实现的。HandlerInterceptor 接口定义了三个方法,分别是 preHandle()、postHandle() 和 afterCompletion()。这些方法在请求处理过程中的不同阶段被调用,具体如下: 1. preHandle() 方法在请求到达控制前被调用,可以用来进行一些前置处理,比如权限校验等。如果该方法返回 false,则请求处理流程会被打断。 2. postHandle() 方法在控制处理完请求后、视图渲染前被调用,可以用来对请求处理结果进行一些后置处理,比如添加一些公共的模型数据等。 3. afterCompletion() 方法在整个请求处理完毕后被调用,可以用来进行一些清理工作,比如释放资源等。 在 Spring MVC 中,我们可以通过配置 Bean 实现拦截的注册和配置。具体步骤如下: 1. 创建一个类,实现 HandlerInterceptor 接口,实现 preHandle()、postHandle() 和 afterCompletion() 方法。 2. 在 Spring 配置文件中配置该类为 Bean,比如: ``` <bean id="myInterceptor" class="com.example.MyInterceptor"/> ``` 3. 在 Spring MVC 配置文件中配置拦截,比如: ``` <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.example.MyInterceptor"/> </mvc:interceptor> </mvc:interceptors> ``` 上面的配置表示将 MyInterceptor 拦截应用于所有的请求路径。我们也可以通过 path 属性指定拦截应用于具体的请求路径。 总的来说,Spring 拦截是一种非常强大的组件,可以帮助我们实现很多通用的功能。掌握了拦截原理和使用方法,我们就可以更好地利用它来提高我们的开发效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盖丽男

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值