Spring拦截器之HandlerInterceptor使用方式

 更新时间:2024年08月21日 15:09:13   作者:?abc!  
这篇文章主要介绍了Spring拦截器之HandlerInterceptor使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

概述

有时候我们需要进行一些预处理后处理,或者是拦截请求,在请求前后后做一些处理

使用Spring MVC框架,那么建议使用HandlerInterceptor,它可以类似于普通bean直接注册到Spring容器中被管理

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

在执行Handler之前(执行业务逻辑之前),根据拦截器链顺序执行

  • 每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法
  • 所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理
  • 也可以在这个方法中进行一些判断来决定请求是否要继续进行下去

该方法的返回值是布尔值Boolean 类型的,

  • 当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;
  • 当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。

postHandle

在执行Handler成功(执行业务逻辑成功)之后,根据拦截器链倒序执行,如果前面的流程中抛出异常或者请求被拦截则不会执行!

  • 在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用
  • 在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,
  • 所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作
  • postHandle 方法被调用的方向跟preHandle 是相反的,也就是说先声明的Interceptor 的postHandle 方法反而会后执行

afterCompletion

在请求处理完毕之后执行,无论是否有响应视图,无论有没有通过preHandle,无论有没有抛出异常。

只会对此前放行成功(preHandle返回true)的拦截器进行倒序调用。

  • 在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用
  • 该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。
  • 这个方法的主要作用是用于进行资源清理工作的

使用

构建拦截器(HandlerInterceptor )

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.gildata.gup.domain.User;
import com.gildata.gup.domain.UserEncryptReset;
import com.gildata.gup.repository.UserEncryptResetRepository;

@Component // 不可少
public class xxxStateInterceptor implements HandlerInterceptor { // 必须实现HandlerInterceptor接口

    
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // TODO Auto-generated method stub
        // ....
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        // TODO Auto-generated method stub
        return;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // TODO Auto-generated method stub
    }
}

注册拦截器(WebMvcConfigurerAdapter )

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.gildata.gup.interceptor.PasswordStateInterceptor;

@Configuration // 配置
public class WebConfigfilter extends WebMvcConfigurerAdapter{
    
    @Autowired
    private XxxStateInterceptor xxxStateInterceptor ; // 实例化拦截器

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // super.addInterceptors(registry);
        // 注册自定义的拦截器passwordStateInterceptor
        registry.addInterceptor(xxxStateInterceptor)
            .addPathPatterns("/api/*") //匹配要过滤的路径
            .excludePathPatterns("/api/changeUser/*") //匹配不过滤的路径。/api/changeUser后面的所有接口不能拦截
            .excludePathPatterns("/api/getAge", "/api/getName") // /api/getAge也不能拦截,/api/getName这个接口的请求不能拦截
    }
}

两个常用方法:

  • .addPathPatterns():增加url的拦截路径,“/**”意思是所有请求都要拦截;
  • .excludePathPatterns():排除url的拦截路径,如:“/api/getAge”, “/api/getName”:意为这两个接口不做拦截;

注意

springBoot2.0以上 WebMvcConfigurerAdapter 方法过时,有两种替代方案:

  • 继承 WebMvcConfigurationSupport 类;
  • 实现 WebMvcConfigurer 接口;

但是,继承WebMvcConfigurationSupport会让Spring-boot对mvc的自动配置失效,所以 建议用实现WebMvcConfigurer接口的方式 。

所以上面的注册拦截器更改为:

@Configuration // 配置
public class WebConfigfilter implements WebMvcConfigurer{
    
    @Autowired
    private XxxStateInterceptor xxxStateInterceptor ; // 实例化拦截器

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // super.addInterceptors(registry);
        // 注册自定义的拦截器passwordStateInterceptor
        registry.addInterceptor(xxxStateInterceptor)
            .addPathPatterns("/api/*") //匹配要过滤的路径
            .excludePathPatterns("/api/changeUser/*") //匹配不过滤的路径。/api/changeUser后面的所有接口不能拦截
            .excludePathPatterns("/api/getAge", "/api/getName") // /api/getAge也不能拦截,/api/getName这个接口的请求不能拦截
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot实现图片防盗链的五种方式详解

    SpringBoot实现图片防盗链的五种方式详解

    出于安全考虑,我们需要后端返回的图片只允许在某个网站内展示,不想被爬虫拿到图片地址后被下载,或者,不想浏览器直接访问图片链接,出于性能考虑,不想要别人的网站,拿着我们的图片链接去展示,所以本文给大家介绍了SpringBoot实现图片防盗链的五种方式
    2025-08-08
  • 使用Spring Security控制会话的方法

    使用Spring Security控制会话的方法

    在本文中,我们将说明Spring Security如何允许我们控制HTTP会话。这篇文章主要介绍了使用Spring Security控制会话 ,需要的朋友可以参考下
    2019-05-05
  • java的arrays数组排序示例分享

    java的arrays数组排序示例分享

    排序算法,基本的高级语言都有一些提供。C语言有qsort()函数,C++有sort()函数,java语言有Arrays类(不是Array)。用这些排序时,都可以写自己的排序规则
    2014-02-02
  • 浅谈springboot @Repository与@Mapper的区别

    浅谈springboot @Repository与@Mapper的区别

    本文主要介绍了浅谈springboot @Repository与@Mapper的区别,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • IDEA+Maven搭建JavaWeb项目的方法步骤

    IDEA+Maven搭建JavaWeb项目的方法步骤

    本文主要介绍了IDEA+Maven搭建JavaWeb项目的方法步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • Java设计模式中责任链模式详解

    Java设计模式中责任链模式详解

    责任链模式是将链中的每一个节点看做是一个对象,每个节点处理的请求均不相同,且内部自动维护下一个节点对象,当一个请求从链式的首段发出时,会沿着链的路径依次传递给每一个节点对象。本文将通过示例和大家详细聊聊责任链模式,需要的可以参考一下
    2022-11-11
  • Java Spring 中 @PostConstruct 注解使用原理及常见场景

    Java Spring 中 @PostConstruct 注解使用原理及常见场景

    在 Java Spring 中,@PostConstruct 注解是一个非常实用的功能,它允许开发者在 Spring 容器完全初始化 Bean 后执行某些操作,本文将详细介绍 @PostConstruct 注解的使用,包括其原理、常见场景和代码示例,
    2025-04-04
  • Java 按照字节来截取字符串的代码(不会出现半个汉字)

    Java 按照字节来截取字符串的代码(不会出现半个汉字)

    Java 按照字节来截取字符串的工具,不会出现半个汉字。一个中文两个字节,一个英文字符只占 1 个字节** 1. 通常我们用于前端显示的时候,防止标题过长
    2014-01-01
  • java面试常问的Runnable和Callable的区别

    java面试常问的Runnable和Callable的区别

    大家好,本篇文章主要讲的是java面试常问的Runnable和Callable的区别,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • Java 在PDF中绘制形状的两种方法

    Java 在PDF中绘制形状的两种方法

    这篇文章主要介绍了Java 在 PDF 中绘制形状的两种实现方法,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07

最新评论