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拦截器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringAOP 如何通过JoinPoint获取参数名和值

    SpringAOP 如何通过JoinPoint获取参数名和值

    这篇文章主要介绍了SpringAOP 通过JoinPoint获取参数名和值的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • java+Okhttp3调用接口的实例

    java+Okhttp3调用接口的实例

    这篇文章主要介绍了java+Okhttp3调用接口的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • SpringBoot属性注入的两种方法

    SpringBoot属性注入的两种方法

    这篇文章主要介绍了SpringBoot属性注入的两种方法,帮助大家更好的理解和使用springboot框架,感兴趣的朋友可以了解下
    2020-11-11
  • Idea 解决 Could not autowire. No beans of ''xxxx'' type found 的错误提示

    Idea 解决 Could not autowire. No beans of ''xxxx'' type found

    这篇文章主要介绍了Idea 解决 Could not autowire. No beans of 'xxxx' type found 的错误提示,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • 一篇文章让你弄懂Java运算符

    一篇文章让你弄懂Java运算符

    java中位运算符主要有按位与&、按位或|、按位非~、按位异或^, 在使用时需要将运算数都转换为二进制再进行运算,若为负数则使用补码表示,这篇文章主要给大家介绍了关于Java运算符的相关资料,需要的朋友可以参考下
    2022-03-03
  • spring mvc中的@PathVariable动态参数详解

    spring mvc中的@PathVariable动态参数详解

    这篇文章主要介绍了spring mvc中的@PathVariable动态参数详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • 创建网关项目(Spring Cloud Gateway)过程详解

    创建网关项目(Spring Cloud Gateway)过程详解

    这篇文章主要介绍了创建网关项目(Spring Cloud Gateway)过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • Spring MVC 自定义数据转换器的思路案例详解

    Spring MVC 自定义数据转换器的思路案例详解

    本文通过两个案例来介绍下Spring MVC 自定义数据转换器的相关知识,每种方法通过实例图文相结合给大家介绍的非常详细,需要的朋友可以参考下
    2021-09-09
  • SpringBoot如何返回Json数据格式

    SpringBoot如何返回Json数据格式

    这篇文章主要介绍了SpringBoot如何返回Json数据格式问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Java定时任务的三种实现方式

    Java定时任务的三种实现方式

    这篇文章主要给大家介绍了关于Java定时任务的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-01-01

最新评论