详解Spring 拦截器流程及多个拦截器的执行顺序

 更新时间:2021年05月06日 11:10:46   作者:码农UP2U  
这篇文章主要介绍了Spring 拦截器流程及多个拦截器的执行顺序的相关资料,帮助大家更好的理解和学习使用Spring框架,感兴趣的朋友可以了解下

       拦截器是 Spring MVC 中的组件,它可以在进入请求方法前做一些操作,也可以在请求方法后和渲染视图后做一些事情。

拦截器的定义

       SpringMVC 的拦截器只需要实现 HandlerInterceptor 接口,并进行配置即可。HandlerInterceptor 接口的定义如下:

public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

       在 HandlerInterceptor 中共有三个方法,每个方法的含义如下:

preHandler:进入请求方法之前执行;

postHandler:请求方法执行完成之后执行;

afterCompletion:视图渲染后执行。

拦截器的执行流程

        在 preHandle 方法中,它的返回值是 boolean 类型的,它的返回值影响着请求方法,以及 postHandle 和 afterCompletion 的执行。具体如下。

        也就是说,在 preHandle 中如果返回 false,那么后续的流程将不被执行,这可能也是拦截器命名的由来。

测试拦截器

       写一个简单拦截器,代码如下:

@Slf4j
public class TestInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("preHandler");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("postHandler");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("afterCompletion");
    }
}

        创建了一个 TestInterceptor 的监听器类,它实现了 HandlerInterceptor 的所有接口。写完 TestInterceptor 还需要进行注册。代码如下:

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(testInterceptor());
    }

        再来写一个简单的请求方法,代码如下:

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

       来启动我们的项目,并进行访问,控制台的输出如下:

2021-05-05 16:02:08.110  INFO 88509 --- [nio-8081-exec-6] com.example.demo.TestInterceptor         : preHandler
2021-05-05 16:02:08.111  INFO 88509 --- [nio-8081-exec-6] com.example.demo.TestInterceptor         : postHandler
2021-05-05 16:02:08.111  INFO 88509 --- [nio-8081-exec-6] com.example.demo.TestInterceptor         : afterCompletion

多个拦截器的执行顺序

        我们来写多个相同的监听器,分别是 TestInterceptor、TestInterceptor2 和 TestInterceptor3。然后我们进行注册,注册代码如下:

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(testInterceptor());
    registry.addInterceptor(testInterceptor2());
    registry.addInterceptor(testInterceptor3());
}

        请求我们的方法,输出如下:

2021-05-05 16:09:57.735  INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor         : preHandler
2021-05-05 16:09:57.736  INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor2        : preHandler2
2021-05-05 16:09:57.736  INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor3        : preHandler3
2021-05-05 16:09:57.755  INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor3        : postHandler3
2021-05-05 16:09:57.755  INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor2        : postHandler2
2021-05-05 16:09:57.755  INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor         : postHandler
2021-05-05 16:09:57.755  INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor3        : afterCompletion3
2021-05-05 16:09:57.755  INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor2        : afterCompletion2
2021-05-05 16:09:57.755  INFO 88572 --- [nio-8081-exec-1] com.example.demo.TestInterceptor         : afterCompletion

        注意观察输出的顺序,preHandle 方法是按注册顺序进行执行的,而 postHandle 和 afterCompletion 跟注册顺序是相反的。

让 preHandle 进行拦截

        我们让 TestInterceptor2 的 preHandle 返回值为 false,然后查看一下输出内容。

2021-05-05 16:14:00.997  INFO 88582 --- [nio-8081-exec-1] com.example.demo.TestInterceptor         : preHandler
2021-05-05 16:14:00.998  INFO 88582 --- [nio-8081-exec-1] com.example.demo.TestInterceptor2        : preHandler2
2021-05-05 16:14:00.998  INFO 88582 --- [nio-8081-exec-1] com.example.demo.TestInterceptor         : afterCompletion

        可以看到,TestInterceptor2 的 preHandle 的返回值为 false 以后,相当于在 TestInterceptor2 的 preHandle 后续流程则不再继续执行了。

        我们调整一下注册的顺序,代码如下:

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(testInterceptor2());
    registry.addInterceptor(testInterceptor());
    registry.addInterceptor(testInterceptor3());
}

       修改顺序后的输出如下:

2021-05-05 16:17:23.956  INFO 88589 --- [nio-8081-exec-1] com.example.demo.TestInterceptor2        : preHandler2

       可以看到它后面的流程都被拦截了,没有机会执行了。

总结

        拦截器是使用一个 List 进行保存,我们可以在项目中添加多个拦截器来完成不同的功能,比如可以进行 Token 的验证,权限的获取等。我们可以放到不同的拦截器中来进行相关的操作。

以上就是详解Spring 拦截器流程及多个拦截器的执行顺序的详细内容,更多关于Spring 拦截器的资料请关注脚本之家其它相关文章!

相关文章

  • JavaMail实现简单邮件发送

    JavaMail实现简单邮件发送

    这篇文章主要为大家详细介绍了JavaMail实现简单邮件发送,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • MyBatis动态sql查询及多参数查询方式

    MyBatis动态sql查询及多参数查询方式

    这篇文章主要介绍了MyBatis动态sql查询及多参数查询方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • maven grpc整合springboot demo

    maven grpc整合springboot demo

    这篇文章主要为大家介绍了基于maven grpc整合springboot demo,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • 教你如何在IDEA 中添加 Maven 项目的 Archetype(解决添加不起作用的问题)

    教你如何在IDEA 中添加 Maven 项目的 Archetype(解决添加不起作用的问题)

    这篇文章主要介绍了如何在 IDEA 中添加 Maven 项目的 Archetype(解决添加不起作用的问题),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • Java报错net.dean.jraw.http.NetworkException异常的原因及解决方法

    Java报错net.dean.jraw.http.NetworkException异常的原因及解决方法

    在开发涉及网络通信的Java应用程序时,我们经常需要处理各种网络异常,net.dean.jraw.http.NetworkException是在使用jRAW库时可能遇到的一个异常,本文将详细探讨NetworkException的成因,并提供多种解决方案,需要的朋友可以参考下
    2024-12-12
  • 在SpringBoot中配置MySQL数据库的详细指南

    在SpringBoot中配置MySQL数据库的详细指南

    在 Spring Boot 中配置数据库是一个相对简单的过程,通常涉及到以下几个步骤:添加数据库驱动依赖、配置数据源属性、以及可选的配置 JPA(如果使用),下面是小编给大家编写的一个详细的指南,以MySQL 数据库为例,需要的朋友可以参考下
    2024-12-12
  • Java设计模式中的单一责任原则详解

    Java设计模式中的单一责任原则详解

    这篇文章主要介绍了Java设计模式中的单一责任原则详解,应该有且仅有一个原因引起类的变更,即单一指责原则要求一个借口或类只有一个原因引起变化,也就是一个接口或类只有一个职责,它就负责一件事情,需要的朋友可以参考下
    2023-11-11
  • Spring整合Kaptcha谷歌验证码工具的开发步骤

    Spring整合Kaptcha谷歌验证码工具的开发步骤

    这篇文章主要介绍了Spring整合Kaptcha谷歌验证码工具的开发步骤,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • Java synchornized与ReentrantLock处理并发出现的错误

    Java synchornized与ReentrantLock处理并发出现的错误

    synchronized机制提供了对每个对象相关的隐式监视器锁,并强制所有锁的获取和释放都必须在同一个块结构中。当获取了多个锁时,必须以相反的顺序释放。即synchronized对于锁的释放是隐式的
    2023-01-01
  • springboot项目启动,但是访问报404错误的问题

    springboot项目启动,但是访问报404错误的问题

    这篇文章主要介绍了springboot项目启动,但是访问报404错误的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12

最新评论