Spring的拦截器HandlerInterceptor详解

 更新时间:2024年01月30日 10:42:39   作者:想养一只萨摩耶~  
这篇文章主要介绍了Spring的拦截器HandlerInterceptor详解,拦截器是相对于Spring中来说的,它和过滤器不一样,过滤器的范围更广一些是相对于Tomcat容器来说的,拦截器可以对用户进行拦截过滤处理,需要的朋友可以参考下

1 什么是拦截器

拦截器是相对于Spring中来说的,它和过滤器不一样,过滤器的范围更广一些是相对于Tomcat容器来说的。拦截器可以对用户进行拦截过滤处理。

但是并不是说拦截器只对请求进入Controller控制器之前起作用,它也分为3个部分:

  • 请求进入Controller之前,通过拦截器执行代码逻辑
  • Controller执行之后(只是Controller执行完毕,视图还没有开始渲染),通过拦截器执行代码逻辑
  • Controller完全执行完毕(整个请求全部结束),通过拦截器执行代码逻辑

2HandlerInterceptor和WebMvcConfigurer

想要自己配置一个拦截器,就必须用到HandlerInterceptor和WebMvcConfigurer这两个接口。

2.1HandlerInterceptor

作用:自定义拦截器

如何创建:这个接口我们通常会自定义一个类。加上@Component注解,并且使它实现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 {
    }
}
  • preHandle:此方法的作用是在请求进入到Controller进行拦截,有返回值。(返回true则将请求放行进入Controller控制层,false则请求结束返回错误信息)

用法:登录验证(判断用户是否登录)权限验证:判断用户是否有权访问资源(校验token)

  • postHandle:该方法是在Controller控制器执行完成但是还没有返回模板进行渲染拦截。没有返回值。就是Controller----->拦截------>ModelAndView。

用法:因此我们可以将Controller层返回来的参数进行一些修改,它就包含在ModelAndView中,所以该方法多了一个ModelAndView参数。

  • afterCompletion:该方法是在ModelAndView返回给前端渲染后执行。

用法:例如登录的时候,我们经常把用户信息放到ThreadLocal中,为了防止内存泄漏,就需要将其remove掉,该操作就是在这里执行的。

2.2WebMvcConfigurer

作用:添加拦截规则

如何创建:自定义一个类,实现WebMvcConfigurer并将它注入到Spring容器中。根据需求实现里面方法。

WebMvcConfigurer源码如下:

public interface WebMvcConfigurer {
    default void configurePathMatch(PathMatchConfigurer configurer) {
    }
    default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    }
    default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
    }
    default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    }
    default void addFormatters(FormatterRegistry registry) {
    }
    default void addInterceptors(InterceptorRegistry registry) {
    }
    default void addResourceHandlers(ResourceHandlerRegistry registry) {
    }
    default void addCorsMappings(CorsRegistry registry) {
    }
    default void addViewControllers(ViewControllerRegistry registry) {
    }
    default void configureViewResolvers(ViewResolverRegistry registry) {
    }
    default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
    }
    default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
    }
    default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    }
    default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    }
    default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    }
    default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    }
    @Nullable
    default Validator getValidator() {
        return null;
    }
    @Nullable
    default MessageCodesResolver getMessageCodesResolver() {
        return null;
    }
}

根据源码发现,这里面有很多方法,但是通常我们只用到了里面的两种方法如下:

addInterceptors:添加拦截器,拦截器需要拦截的路径和需要排除拦截的路径都需要在其中配置

addResourceHandlers:配置静态资源路径,即某些请求需要读取某个路径下的静态资源内容,需要配置该静态资源的路径,通过该方法可以统一给这些请求配置指定静态资源路径

3 拦截器实现流程

根据第二部分,我们知道了配置拦截器的准备工作。

1)自定义类实现HandlerInterceptor

@Component
public class HeaderInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("进入拦截器=======执行前========");
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("进入拦截器=======执行中========");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("进入拦截器=======执行后========");
    }
}

2)自定义类实现WebMvcConfigurer

package com.liubujun.springbootinterceptor.config;
import com.liubujun.springbootinterceptor.interceptor.HeaderInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
 * @Author: liubujun
 * @Date: 2022/10/10 19:55
 */
/**
 * 此处也可以继承WebMvcConfigurationSupport
 */
@Configuration
public class WebAppConfig implements WebMvcConfigurer {
    @Resource
    private HeaderInterceptor headerInterceptor;
    /**
     * 添加拦截规则
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> patterns = new ArrayList<>();
        patterns.add("/login/login");
        registry.addInterceptor(headerInterceptor)
                .addPathPatterns("/**") //所有的请求都要拦截。
                .excludePathPatterns(patterns); //将不需要拦截的接口请求排除在外
    }
    /**
     * //下面代码意思是:配置一个拦截器,如果访问路径时addResourceHandler中的这个路径(我这里是/**表示所有的路径),
     *  那么就映射到访问本地的addResourceLocations这个路径上,这样就可以看到该路径上的资源了
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**") //配置需要添加静态资源请求的url
                .addResourceLocations("classpath:/pic/"); //配置静态资源路径
    }
}

3)测试类

@RestController
public class LoginController {
 
 
    @GetMapping("/login/login")
    public String testLoginInterceptor(){
        return "登录请求没有被拦截====》看控制台没有输出";
    }
 
    @GetMapping("/test/other")
    public String testOtherInterceptor(){
        return "该请求没有被拦截,看控制台有输出";
    }
}

4)本地添加静态资源

猜验证1:

由于在配置拦截规则中,拦截了所有请求,但是排除了登录请求,所以

/login/login 请求正常访问,但不会进入拦截器,故控制台不会打印拦截器中的输出语句。

验证2:

由于在配置拦截规则

由于在配置拦截规则中,拦截了所有请求,但是排除了登录请求,所以

/test/other请求正常访问,会进入拦截器,控制台会打印拦截器中的输出语句。

验证3:拦截器中配置了映射静态资源路径,所以可以访问到自己上传到本地服务器的图片。

到此这篇关于Spring的拦截器HandlerInterceptor详解的文章就介绍到这了,更多相关HandlerInterceptor拦截器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java消息队列RabbitMQ之消息模式详解

    Java消息队列RabbitMQ之消息模式详解

    这篇文章主要介绍了Java消息队列RabbitMQ之消息模式详解,RabbitMQ提供了一种qos(服务质量保证)功能,即在非自动确认消息的前提下,如果一定数目的消息(通过基于Consumer或者Channel设置Qos的值)未被确认前,不进行消费新的消息,需要的朋友可以参考下
    2023-07-07
  • Spring Security基于过滤器实现图形验证码功能

    Spring Security基于过滤器实现图形验证码功能

    验证码就是为了防止恶意用户采用暴力重试的攻击手段而设置的一种防护措施,接下来在Spring Security的环境中,我们可以用两种方案实现图形验证码,具体实现方法跟随小编一起看看吧
    2021-09-09
  • JAVA熔断和降级真实关系的图文详解

    JAVA熔断和降级真实关系的图文详解

    这篇文章主要介绍了Java熔断和降级的关系,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • SpringData JPA快速上手之关联查询及JPQL语句书写详解

    SpringData JPA快速上手之关联查询及JPQL语句书写详解

    JPA都有SpringBoot的官方直接提供的starter,而Mybatis没有,直到SpringBoot 3才开始加入到官方模版中,这篇文章主要介绍了SpringData JPA快速上手,关联查询,JPQL语句书写的相关知识,感兴趣的朋友一起看看吧
    2023-09-09
  • Java Annotation注解相关原理代码总结

    Java Annotation注解相关原理代码总结

    这篇文章主要介绍了Java Annotation注解相关原理代码总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • Kotlin教程之函数和包的定义和流程控制

    Kotlin教程之函数和包的定义和流程控制

    这篇文章主要介绍了Kotlin教程之函数和包的定义和流程控制的相关资料,需要的朋友可以参考下
    2017-05-05
  • java巧用@Convert实现表字段自动转entity

    java巧用@Convert实现表字段自动转entity

    本文主要介绍了java巧用@Convert实现表字段自动转entity,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-07-07
  • 在Java中使用OpenCV实践

    在Java中使用OpenCV实践

    用户分享了在Java项目中集成OpenCV4.10.0的实践经验,涵盖库简介、Windows安装、依赖配置及灰度图测试,强调其在图像处理领域的多功能性,并计划后续探索AI结合应用
    2025-07-07
  • 解决JDK8的ParallelStream遍历无序的问题

    解决JDK8的ParallelStream遍历无序的问题

    这篇文章主要介绍了解决JDK8的ParallelStream遍历无序的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Java单链表的实现代码

    Java单链表的实现代码

    这篇文章主要介绍了Java单链表的实现代码的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-07-07

最新评论