【Spring Boot 拦截器介绍】

文章目录

  • 一、Spring Boot 拦截器是什么?
    • 1. 拦截器与过滤器的区别
      • 过滤器(Filter)
      • 拦截器(Interceptor)
  • 二、Spring Boot 拦截器的使用场景
    • 身份验证和授权
    • 日志记录
    • 性能监测
    • 通用行为的应用
  • 三、如何实现 Spring Boot 拦截器
    • 1. 创建拦截器类
    • 2. 注册拦截器
  • 四、高级配置
    • 1. 拦截器链
      • 配置拦截器链
    • 2. 动态拦截器
      • 实现动态拦截
    • 3. 异常处理
      • 在拦截器中处理异常

一、Spring Boot 拦截器是什么?

拦截器允许开发者在处理 HTTP 请求的生命周期的不同阶段—即请求处理之前、之后以及请求完成后—执行特定的操作。这些操作可以包括日志记录、身份验证、权限检查、事务管理等。

1. 拦截器与过滤器的区别

理解拦截器之前,有必要区分两个经常被混用的概念:拦截器(Interceptor)和过滤器(Filter)。

过滤器(Filter)

过滤器是 Java Servlet 规范的一部分,它在 Servlet 层面上提供了一种方式来处理请求和响应。过滤器可以对几乎所有的请求进行拦截,因为它们工作在请求的前端(在请求达到控制器之前)和后端(在响应被发送回客户端之前)。过滤器主要用于请求的预处理、响应的后处理,以及请求链中的请求/响应转换。

拦截器(Interceptor)

与过滤器相比,拦截器是 Spring MVC 提供的,它提供了更精细的控制。拦截器仅作用于处理器映射到的方法。这意味着,它们可以访问控制器执行的上下文,包括执行的控制器本身和控制器方法的元数据。拦截器可以在以下三个阶段执行操作:

  • preHandle:在 Controller 方法调用之前执行。可以进行身份验证、权限检查等操作,并决定是否中断执行链,即是否将请求传递给控制器处理。
  • postHandle:在 Controller 方法调用之后,但在视图被渲染之前执行。可以对模型数据进行操作或对视图进行处理。
  • afterCompletion:在整个请求结束后执行,即在视图渲染完毕后。这里可以进行资源清理等操作。

拦截器提供了一种更为灵活和强大的方式来插入跨越请求处理生命周期的逻辑。相比之下,过滤器更适合处理如请求日志记录、请求和响应的通用处理(比如设置响应头)等跨应用程序的共通行为。

二、Spring Boot 拦截器的使用场景

身份验证和授权

身份验证和授权是几乎每个应用必须处理的关键安全问题。通过拦截器,在请求到达目标控制器之前,可以检查用户的认证状态和权限。如果用户未经认证或缺乏访问特定资源的权限,拦截器可以阻止请求继续处理并直接返回一个错误响应或重定向到登录页面。这样的处理确保了应用的安全性,同时保持了控制器逻辑的清晰和专注。

日志记录

日志记录是开发和维护过程中的一个重要方面,它帮助开发者了解应用的运行状态,以及在出现问题时进行调试。通过拦截器,可以在请求处理的前后记录下请求路径、请求参数、用户身份等详细信息。这不仅有助于监控应用的健康状况,也为故障排查和性能分析提供了宝贵信息。

性能监测

在性能敏感的应用中,监测和优化请求的处理时间是提高用户体验的关键。拦截器可以用于监控请求的处理时间,通过记录请求开始和完成的时间,可以计算出处理每个请求所需的时间。这些数据可以用于识别性能瓶颈,指导后续的优化工作。

通用行为的应用

在多个控制器或请求处理流程中需要应用的通用行为,如跨域资源共享(CORS)设置、语言偏好处理、时区信息设置等,都可以通过拦截器以统一和非侵入式的方式实现。例如可以在拦截器中统一处理跨域请求的头信息,或根据请求头或参数调整语言和时区设置,从而提高代码的复用性和维护性。

三、如何实现 Spring Boot 拦截器

1. 创建拦截器类

首先需要定义一个类实现 HandlerInterceptor 接口或继承 HandlerInterceptorAdapter 类。这个接口定义了三个方法:preHandlepostHandleafterCompletion,分别对应于请求处理的前、中、后三个阶段。

  • preHandle:在请求处理之前进行调用(Controller方法调用之前)。这里可以进行权限验证、日志记录等操作。如果返回值为false,Spring MVC将不会继续处理这个请求。
  • postHandle:在请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)。可以通过这个方法对模型数据进行处理或对视图进行处理。
  • afterCompletion:在整个请求结束之后被调用,也就是在DispatcherServlet渲染了对应的视图之后执行(主要用于进行资源清理工作)。
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 在Controller执行之前调用
        // 这里可以进行权限验证、日志记录等
        return true; // 返回true则继续执行下一个拦截器或处理器
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在Controller执行之后调用,但在视图渲染之前
        // 这里可以对模型数据进行处理或对视图进行处理
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 在请求完全结束后调用,可用于清理资源等
    }
}

2. 注册拦截器

创建拦截器类之后,需要将其注册到 Spring MVC 的拦截器链中以启用其功能。可以通过实现 WebMvcConfigurer 接口并重写 addInterceptors 方法来完成。

WebMvcConfigurer 中可以定义拦截器的应用规则,比如指定拦截器应该拦截哪些URL路径。通过调用 InterceptorRegistryaddInterceptor 方法,并通过 addPathPatterns 方法来指定路径模式,可以非常灵活地配置拦截器的应用范围。

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.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private MyInterceptor myInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册拦截器,并指定拦截的路径
        registry.addInterceptor(myInterceptor).addPathPatterns("/**");
        // 你也可以通过addPathPatterns添加多个匹配模式,或通过excludePathPatterns排除某些模式
    }
}

四、高级配置

1. 拦截器链

在 Spring Boot 应用中,可以通过配置多个拦截器来形成一个拦截器链。Spring MVC 会按照拦截器注册的顺序依次调用这些拦截器,执行它们的 preHandlepostHandleafterCompletion 方法。

配置拦截器链

WebMvcConfigurer 的实现类中,可以通过调用 addInterceptors 方法多次添加多个拦截器,从而形成一个链。每个拦截器可以定义自己的拦截路径模式,也可以有共同的路径模式。

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new FirstInterceptor()).addPathPatterns("/**");
    registry.addInterceptor(new SecondInterceptor()).addPathPatterns("/api/**");
}

这个例子中,所有请求都会被 FirstInterceptor 拦截,而只有 /api/** 路径的请求会被 SecondInterceptor 拦截。

2. 动态拦截器

动态拦截器允许开发者根据请求的动态信息,如 URL、Header 等,来决定是否执行拦截器。可以通过在 preHandle 方法中添加逻辑来实现。

实现动态拦截

public class DynamicInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 根据请求的 URL 或 Header 决定是否进行拦截
        String headerValue = request.getHeader("X-Intercept");
        if ("true".equals(headerValue)) {
            // 执行某些操作
            return true; // 继续执行拦截器链
        } else {
            // 跳过当前拦截器,不对请求进行处理
            return false; // 中断执行,这将阻止控制器方法的执行
        }
    }
}

这个例子中,拦截器会检查请求头 X-Intercept 的值,根据这个值来决定是否进行后续操作。

3. 异常处理

在拦截器中处理异常

拦截器本身并不直接处理异常。相反,应当将异常信息传递给 Spring MVC 的异常处理机制。

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    if (ex != null) {
        // 记录异常信息,或者使用其他方式处理异常
        // 例如,可以将异常信息包装后抛出自定义异常
        throw new CustomException("Interceptor error", ex);
    }
}

在这个例子中,如果 afterCompletion 方法接收到异常,它会记录异常信息或抛出自定义异常。应用中应该有全局异常处理器(如使用 @ControllerAdvice 注解的类)来进一步处理这些异常,例如返回一个友好的错误响应给用户。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/770084.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GNU/Linux - Kconfig Language - 1

Introduction 配置数据库是以树形结构组织的配置选项集合: The configuration database is a collection of configuration options organized in a tree structure: - Code maturity level options | - Prompt for development and/or incomplete code/drivers …

hibernate与jpa学习

jpa是一个规范,hibernate是jpa的实现,是一种框架。 hibernate: ORM框架/持久层框架(Object Relational Mapping) 它是是一个轻量级开放源代码的对象关系映射框架,hibernate可以自动生成SQL语句&#xff0…

js 使用 lodash-es 检测某个值是否是函数

import { isFunction } from lodash-eslet isA isFunction(() > {}) console.log(isA) //true https://www.lodashjs.com/docs/lodash.isFunction#_isfunctionvalue https://lodash.com/docs/4.17.15#isFunction 人工智能学习网站 https://chat.xutongbao.top

简单的电路指示锂离子电池的健康状况

锂离子电池对不良处理很敏感。当我们将电池充电至低于制造商定义的裕量时,可能会发生火灾、爆炸和其他危险情况。 锂离子电池在正常使用的过程中,其内部进行电能与化学能相互转化的化学正反应。但在某些条件下,如对其过充电、过放电或过电流…

复杂流分类

拓扑图 配置 配置ACL 配置流分类、流行为、流策略 在接口应用 sysname AR1 # acl number 2000 rule 5 permit source 10.1.1.1 0 acl number 2001 rule 5 permit source 10.1.1.2 0 acl number 2002 rule 5 permit source 10.1.1.3 0 # traffic classifier EF operat…

CGLib动态代理技术

基于CGLib的动态代理机制,ProxyFactoryy无需再像JDK动态代理那样实现一个interface,实际情况下可能这个interface并不存在,只需要实现另外一个接口MethodInterceptor即可 package com.hmdp.service.尚硅谷的代理模式3; //CGlib代理import …

FlinkSQL 开发经验分享

作者:汤包 最近做了几个实时数据开发需求,也不可避免地在使用 Flink 的过程中遇到了一些问题,比如数据倾斜导致的反压、interval join、开窗导致的水位线失效等问题,通过思考并解决这些问题,加深了我对 Flink 原理与机…

Android 开发中 C++ 和Java 日志调试

在 C 中添加堆栈日志 先在 Android.bp 中 添加 ‘libutilscallstack’ shared_libs:["liblog"," libutilscallstack"]在想要打印堆栈的代码中添加 #include <utils/CallStack.h> using android::CallStack;// 在函数中添加 int VisualizerLib_Crea…

制作一个动态库

1. 准备工作 # 目录结构 add.c div.c mult.c sub.c -> 算法的源文件, 函数声明在头文件 head.h # main.c中是对接口的测试程序, 制作库的时候不需要将 main.c 算进去 . ├── add.c ├── div.c ├── include │ └── head.h ├── main.c ├── mult.c └── s…

Day04-jenkins-docker

Day04-jenkins-docker 9. 案例06: 基于docker的案例实现静态代码9.1 整体流程9.2 步骤与环境1) 步骤2) 环境 9.3 详细步骤1&#xff09;代码准备2&#xff09;书写dockerfile3&#xff09;准备私有仓库4&#xff09;创建jenkins任务5&#xff09;web节点上启动对应的docker容器…

WPF真入门教程34--爆肝了【仓库管理系统】

1、项目介绍 本项目是一个基于C#WPF实现的仓库管理系统&#xff0c;系统规模较小&#xff0c;适合入门级的项目练练手&#xff0c;但项目还是具有较高的学习价值&#xff0c;它采用mvvmlight框架&#xff0c;EF框架&#xff0c;WPF前端等技术构成。对于学习来说&#xff0c;可…

Ubuntu设置nacos开机以单机模式自启动

首先&#xff0c;需要安装jdk Ubuntu 安装JDK 创建Systemd服务单元文件 sudo vim /etc/systemd/system/nacos.service按i进入编辑模式&#xff0c;写入下面信息 [Unit] Descriptionnacos server Afternetwork.target[Service] Typeforking Environment"JAVA_HOME/opt/j…

树莓派0 2W重启后突然没有声音

树莓派0 2W重启后突然没有声音。 最近在使用该板卡。重启后突然出现了显示器不能显示界面的情况&#xff0c;接着用putty的ssh方式连接该板卡&#xff0c;能连上。使用vnc方式连接该板卡&#xff0c;也能连上。后来通过修改/boot/config.txt文件&#xff0c;能在显示器上显示界…

AI大模型深度学习:理论与应用全方位解析

背景 在当前技术环境下&#xff0c;AI大模型学习不仅要求研究者具备深厚的数学基础和编程能力&#xff0c;还需要对特定领域的业务场景有深入的了解。通过不断优化模型结构和算法&#xff0c;AI大模型学习能够不断提升模型的准确性和效率&#xff0c;为人类生活和工作带来更多…

用一百场线下讲座科普充电桩 能效电气做到了

在新能源汽车产业蓬勃发展的今天,充电桩作为产业链的重要环节,其建设与发展成为推动行业进步的关键。在这一背景下,能效电气凭借其卓越的技术实力和前瞻性的市场布局,成为了新能源充电桩行业的佼佼者。 为了进一步推动新能源产业的发展,普及充电桩知识,能效电气精心策划并举办…

LangChain的基本构成、组件与典型场景

【图书推荐】《ChatGLM3大模型本地化部署、应用开发与微调》-CSDN博客 在人工智能的持续演进中&#xff0c;语言模型&#xff0c;尤其是大型语言模型&#xff08;LLM&#xff09;&#xff0c;例如备受瞩目的ChatGPT&#xff0c;已经稳固地占据了科技前沿的核心地位。这些模型不…

ChatGPT 论文助手:如何用 AI 技术加速学术写作过程

ChatGPT在论文写作中的应用 ChatGPT作为一个先进的语言模型&#xff0c;在学术论文创作领域提供显著帮助。它不仅提升学生与研究者的写作效率&#xff0c;还优化论文质量并引入创新观点。以下是ChatGPT在论文写作中的几种具体应用&#xff1a; 提升写作效率 生成写作构思&…

Mac密室逃脱游戏推荐:Escape Simulator for mac安装包

Escape Simulator 是一款逃生模拟游戏&#xff0c;玩家在游戏中需要寻找线索、解决谜题&#xff0c;以逃离各种房间或环境。这种类型的游戏通常设计有多个关卡或场景&#xff0c;每个场景都有不同的设计和难度。 在 Escape Simulator 中&#xff0c;玩家的目标通常是找到出口或…

Springboot+Vue3开发学习笔记《1》

SpringbootVue3开发学习笔记《1》 博主正在学习SpringbootVue3开发&#xff0c;希望记录自己学习过程同时与广大网友共同学习讨论。 一、前置条件 博主所用版本&#xff1a; IDEA需要破解&#xff0c;破解工具链接容易挂&#xff0c;关注私聊我单发。 Spring Boot是Spring提…

Zabbix 配置WEB监控

Zabbix WEB监控介绍 在Zabbix中配置Web监控&#xff0c;可以监控网站的可用性和响应时间。Zabbix提供了内置的Web监控功能&#xff0c;通过配置Web场景&#xff08;Web Scenario&#xff09;&#xff0c;可以监控HTTP/HTTPS协议下的Web服务。 通过Zabbix的WEB监控可以监控网站…