当前位置: 首页 > article >正文

Spring Boot过滤器链:从入门到精通

文章目录

    • 一、过滤器链是什么?
    • 二、为什么需要过滤器链?
    • 三、Spring Boot中的过滤器链是如何工作的?
      • (一)过滤器的生命周期
      • (二)过滤器链的执行流程
    • 四、如何在Spring Boot中定义自己的过滤器?
    • 五、如何控制过滤器的顺序?
    • 六、Spring Security中的过滤器链
    • 七、过滤器链的性能优化
    • 八、总结

在当今的Web开发中,Spring Boot凭借其简洁高效的特性,成为了众多开发者的首选框架。而过滤器链作为Spring Boot中一个重要的概念,对于保障应用的安全性和功能完整性起着关键作用。今天,就让我们一起深入了解Spring Boot中的过滤器链,从入门到精通,一步步揭开它的神秘面纱。

一、过滤器链是什么?

在Spring Boot中,过滤器链(Filter Chain)是由一系列过滤器(Filter)组成的有序集合。这些过滤器按照一定的顺序依次对请求进行处理,每个过滤器都可以对请求进行拦截、修改或增强操作,从而实现诸如安全检查、日志记录、请求转发等功能。过滤器链的设计使得我们可以将不同的功能模块化,通过组合多个过滤器来实现复杂的功能逻辑,同时保持代码的清晰和可维护性。

二、为什么需要过滤器链?

在Web应用中,我们常常需要在请求到达业务逻辑之前或之后执行一些通用的操作。例如,在请求到达控制器之前,我们可能需要验证用户的身份、记录请求的日志;在响应返回给客户端之前,我们可能需要对响应内容进行压缩或加密。如果这些操作都直接写在业务逻辑代码中,会导致代码的耦合度很高,难以维护和扩展。而过滤器链的出现,正是为了解决这个问题。通过将这些通用操作封装到不同的过滤器中,并按照一定的顺序组织成过滤器链,我们可以在不修改业务逻辑代码的情况下,灵活地添加或修改这些通用操作,从而提高代码的可维护性和可扩展性。

三、Spring Boot中的过滤器链是如何工作的?

(一)过滤器的生命周期

在Spring Boot中,每个过滤器都遵循一个标准的生命周期,主要包括以下三个阶段:

  • 初始化(init):当过滤器被创建时,Spring会调用过滤器的init方法。在这个方法中,我们可以进行一些初始化操作,例如加载配置文件、初始化资源等。不过,在Spring Boot中,由于过滤器通常是通过Spring的依赖注入机制进行管理的,因此我们很少需要手动实现init方法。
  • 过滤(doFilter):这是过滤器的核心方法,当请求到达过滤器时,Spring会调用doFilter方法。在这个方法中,我们可以对请求进行拦截、修改或增强操作。例如,我们可以在doFilter方法中验证用户的身份,如果用户未登录,则直接返回401状态码;如果用户已登录,则继续调用下一个过滤器。doFilter方法的参数包括ServletRequest、ServletResponse和FilterChain,其中FilterChain表示过滤器链的下一个过滤器,通过调用FilterChain的Filterdo方法,可以将请求传递给下一个过滤器。
  • 销毁(destroy):当过滤器被销毁时,Spring会调用过滤器的destroy方法。在这个方法中,我们可以进行一些清理操作,例如关闭资源、释放内存等。和init方法一样,在Spring Boot中,我们也很少需要手动实现destroy方法。

(二)过滤器链的执行流程

当一个请求到达Spring Boot应用时,Spring会按照过滤器链中过滤器的顺序依次调用每个过滤器的doFilter方法。每个过滤器都可以对请求进行处理,然后通过调用FilterChain的doFilter方法将请求传递给下一个过滤器。如果某个过滤器不想让请求继续传递下去,它可以选择不调用FilterChain的doFilter方法,从而直接返回响应给客户端。例如,如果一个过滤器发现用户未登录,它可以直接返回401状态码,而不再调用下一个过滤器。
过滤器链的执行流程可以用以下伪代码来表示:

filterChain.doFilter(ServletRequest request, ServletResponse response) {for (Filter filter : filters) {filter.doFilter(request, response, new FilterChain() {@Overridepublic void doFilter(ServletRequest request, ServletResponse response) {// 调用下一个过滤器FilterChain.doFilter(request, response);}});}
}

从这个伪代码中可以看出,过滤器链的执行是一个递归的过程,每个过滤器都负责调用下一个过滤器的doFilter方法,直到所有的过滤器都执行完毕,请求才会最终到达业务逻辑代码。

四、如何在Spring Boot中定义自己的过滤器?

在Spring Boot中,定义自己的过滤器非常简单。我们只需要创建一个类,让它实现javax.servlet.Filter接口,然后在类上添加@Component注解,让Spring能够自动扫描并注册这个过滤器。以下是一个简单的自定义过滤器示例:

import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;@Component
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化操作System.out.println("MyFilter初始化");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 在请求到达业务逻辑之前执行的操作System.out.println("MyFilter请求前处理");HttpServletRequest httpRequest = (HttpServletRequest) request;System.out.println("请求路径:" + httpRequest.getRequestURI());// 调用下一个过滤器chain.doFilter(request, response);// 在响应返回给客户端之前执行的操作System.out.println("MyFilter响应后处理");}@Overridepublic void destroy() {// 销毁操作System.out.println("MyFilter销毁");}
}

在上面的代码中,我们定义了一个名为MyFilter的过滤器。在doFilter方法中,我们在请求到达业务逻辑之前打印了一条日志,并获取了请求的路径;在响应返回给客户端之前,我们又打印了一条日志。通过在类上添加@Component注解,Spring会自动扫描并注册这个过滤器,将其加入到过滤器链中。

五、如何控制过滤器的顺序?

在Spring Boot中,过滤器链中过滤器的执行顺序是由过滤器的优先级决定的。默认情况下,Spring会按照过滤器的类名的字典顺序对过滤器进行排序。但是,我们可以通过实现Ordered接口或使用@Order注解来指定过滤器的优先级。优先级越小,过滤器越先执行。
以下是一个使用@Order注解指定过滤器优先级的示例:

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;import javax.servlet.*;
import.io java.IOException;@Component
@Order(1)
public class FirstFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("FirstFilter初始化");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("FirstFilter请求前处理");chain.doFilter(request, response);System.out.println("First响应Filter后处理");}@Overridepublic void destroy() {System.out.println("FirstFilter销毁");}
}@Component
@Order(2)
public class SecondFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("SecondFilter初始化");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("SecondFilter请求前处理");chain.doFilter(request, response);System.out.println("SecondFilter响应后处理");}@Overridepublic void destroy() {System.out.println("SecondFilter销毁");}
}

在上面的代码中,我们定义了两个过滤器FirstFilter和SecondFilter,并通过@Order注解分别指定了它们的优先级为1和2。因此,在过滤链器中,FirstFilter会先于SecondFilter执行。

六、Spring Security中的过滤器链

Spring Security是Spring Boot中用于实现安全认证和授权的框架,它也使用了过滤器链来实现各种安全功能。Spring Security的过滤器链中包含了许多预定义的过滤器,例如SecurityContextPersistenceFilter用于在请求开始时恢复安全上下文,在请求结束时清理安全上下文;UsernamePasswordAuthenticationFilter用于处理基于用户名和密码的登录请求;ExceptionTranslationFilter用于处理安全相关的异常,例如用户未登录或没有权限访问某个资源等。
通过自定义过滤器并将其加入到Spring Security的过滤器链中,我们可以扩展Spring Security的功能,实现自己的安全需求。例如,我们可以通过自定义一个过滤器来实现基于JWT(JSON Web Token)的认证机制,或者通过自定义一个过滤器来实现对请求的访问控制。
以下是一个将自定义过滤器加入到Spring Security过滤器链中的示例:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.addFilterBefore(new MyCustomFilter(), UsernamePasswordAuthenticationFilter.class).authorizeRequests().anyRequest().authenticated().and().formLogin().permitAll().and().logout().permitAll();}
}

在的上面代码中,我们通过addFilterBefore方法将自定义的MyCustomFilter加入到了Spring Security的过滤器链中,并指定它在UsernamePasswordAuthenticationFilter之前执行。这样,我们就可以在用户登录之前对请求进行处理,例如验证请求的来源是否合法等。

七、过滤器链的性能优化

虽然过滤器链为我们提供了强大的功能,但是过多的过滤器或不合理的过滤器链设计可能会对应用的性能产生影响。以下是一些优化过滤器链性能的建议:
减少不必要的过滤器:只在真正需要的地方使用过滤器,避免在每个请求上都执行不必要的操作。例如,如果某个过滤器只对特定的请求路径有效,可以通过在doFilter方法中添加路径匹配逻辑来减少不必要的调用。
优化过滤器的实现:在过滤器的doFilter方法中,尽量减少对资源的占用和对性能的影响。例如,避免在过滤器中进行复杂的计算或大量的I/O操作。
合理安排过滤器的顺序:将那些可以快速拒绝请求的过滤器放在前面,例如安全过滤器或权限过滤器,这样可以减少不必要的后续处理。
使用异步过滤器:如果过滤器的操作可以异步执行,可以考虑使用AsyncFilter来提高性能。异步过滤器可以在不阻塞主线程的情况下执行耗时操作,从而提高应用的并发能力。

八、总结

通过本文的介绍,我们从过滤器链的基本概念出发,逐步深入到了Spring Boot中过滤器链的实现原理、定义方法、顺序控制以及与Spring Security的结合等方面。过滤器链作为一种强大的功能,可以帮助我们实现各种通用的操作,提高代码的可维护性和可扩展性。然而,在使用过滤器链时,我们也需要注意性能优化,避免对应用的性能产生负面影响。

相关文章:

Spring Boot过滤器链:从入门到精通

文章目录 一、过滤器链是什么?二、为什么需要过滤器链?三、Spring Boot中的过滤器链是如何工作的?(一)过滤器的生命周期(二)过滤器链的执行流程 四、如何在Spring Boot中定义自己的过滤器&#…...

关于 IoT DC3 中驱动(Driver)的理解

在开源IoT DC3物联网系统中,驱动(Driver)扮演着至关重要的角色,它充当了软件系统与物理设备之间的桥梁。驱动的主要功能是依据特定的通信协议连接到设备,并根据设备模板中配置的位号信息进行数据采集和指令控制。不同的…...

微信小程序地图标记点,安卓手机一次性渲染不出来的问题

问题描述: 如果微信小程序端,渲染的标记物太多,安卓手机存在标记物不显示的问题,原因初步判断是地图还没有渲染完,标记物数据已经加载完了,导致没有在地图上显示。 解决办法: 使用map组件的b…...

一维差分与二维差分

差分(Difference)是一种与前缀和密切相关的技术,主要用于高效处理区间更新操作。差分数组的核心思想是通过记录相邻元素的差值来表示原数组的变化,从而将区间更新操作的时间复杂度从 O(n) 优化到 O(1)。下面详细讲解一维差分和二维…...

EasyRTC嵌入式WebRTC视频通话SDK支持Web浏览器、Linux、ARM、Android、iOS

随着互联网技术的飞速发展,实时通信(RTC)已经成为现代应用中不可或缺的一部分。无论是视频会议、在线教育、远程医疗,还是社交娱乐,实时通信技术都在其中扮演着重要角色。 然而,WebRTC技术在PC和移动端的支…...

数据库脚本MySQL8转MySQL5

由于生产服务器版本上部署的是MySQL5,而开发手里的脚本代码是MySQL8。所以只能降版本了… 升级版本与降级版本脚本转换逻辑一样 MySQL5与MySQL8版本SQL脚本区别 大多数无需调整、主要是字符集与排序规则 MySQL5与MySQL8版本SQL字符集与排序规则 主要操作&…...

【PGCCC】commit_delay 对性能的提升:PostgreSQL 基准测试

通过禁用参数可以来调整事务工作负载synchronous_commit。该措施有惊人效果。但在操作系统崩溃期间丢失已提交事务的可能性使其成为许多应用程序无法启动的因素。因此我决定写下来。 WAL 刷新是事务数据库工作负载的瓶颈 为了确保已提交的事务不会丢失,PostgreSQL…...

AI大模型随机初始化权重并打印网络结构方法(以Deepseekv3为例,单机可跑)

背景 当前大模型的权重加载和调用,主要是通过在HuggingFace官网下载并使用transformer的库来加以实现;其中大模型的权重文件较大(部分>100GB),若只是快速研究网络结构和数据流变化,则无需下载权重。本文…...

字符串解码——巧妙使用递归解题

题目描述 给定一个经过编码的字符串,返回它解码后的字符串。编码规则为 k[encoded_string],表示方括号内部的 encoded_string 重复 k 次。其中 k 是正整数,输入字符串确保符合格式要求且无额外空格。 示例: 复制 示例 1&#…...

Flask Web开发的重要概念和示例

一口气列举Flask Web应用的所有概念和示例 Flask Web 应用基本框架 路由(Routing) 模版(Template) request 对象 JSON 数据处理 redirect 示例 文件上传示例 文件下载示例 Session 示例 Cookie操作 Flask Web 应用基本框架 这是一个 最基础的 Flask Web 应用,…...

51-ArrayList

51-ArrayList Collection 类型介绍 仓颉中常用的几种基础 Collection 类型,包含 Array、ArrayList、HashSet、HashMap。 可以在不同的场景中选择适合对应业务的类型: Array:如果不需要增加和删除元素,但需要修改元素&#xff…...

Ollama+WebUI+DeepSeek部署自己的本地大模型

前言 使用AI几乎成为互联网工作者必备技能了,DeepSeek的出现把AI再次推向高潮,在本文中,我们将带领大家借助 Ollama、WebUI 和 deepseek 这三个工具,成功搭建属于自己的本地大模型环境。Ollama 作为一款轻量级的大模型运行工具&a…...

(篇六)基于PyDracula搭建一个深度学习的软件之新版本ultralytics-8.3.28调试

ultralytics-8.3.28版本debug记录 1传入文件 代码太多不粘贴在这里了,完整代码写在了篇三 def open_src_file(self):config_file config/fold.jsonconfig json.load(open(config_file, r, encodingutf-8))open_fold config[open_fold]if not os.path.exists(op…...

NLP Word Embeddings

Word representation One-hot形式 在上一周介绍RNN类模型时,使用了One-hot向量来表示单词的方式。它的缺点是将每个单词视为独立的,算法很难学习到单词之间的关系。 比如下面的例子,即使语言模型已经知道orange juice是常用组合词&#xf…...

基于 FPGA 的嵌入式系统硬件逻辑优化技术探究

在数字化浪潮席卷全球的当下,嵌入式系统已然成为众多领域不可或缺的核心力量。从我们日常使用的智能手机、智能穿戴设备等消费电子产品,到关乎工业生产效率与精度的工业控制系统,再到汽车电子领域的自动驾驶辅助系统以及航空航天领域的飞行器…...

使用HX搭建UNI-APP云开发项目(适合新手小白与想学云开发的宝子)

什么是uni-app云开发 uni-app云开发是uni-app提供的一套后端服务,它可以帮助开发者快速搭建起一个完整的后端服务,包括数据库、云函数、存储等。开发者只需要关注前端页面的开发,后端服务由uni-app云开发提供。 uni-app云开发的优势: 快速搭建后端服务:uni-app云开发提供了…...

sql:时间盲注和boolen盲注

关于时间盲注&#xff0c;boolen盲注的后面几个获取表、列、具体数据的函数补全 时间盲注方法 import time import requests# 获取数据库名 def inject_database(url):dataname for i in range(1, 20):low 32high 128mid (low high) // 2while low < high:payload &q…...

【STM32】ADC|多通道ADC采集

本次实现的是ADC实现数字信号与模拟信号的转化&#xff0c;数字信号时不连续的&#xff0c;模拟信号是连续的。 1.ADC转化的原理 模拟-数字转换技术使用的是逐次逼近法&#xff0c;使用二分比较的方法来确定电压值 当单片机对应的参考电压为3.3v时&#xff0c;0~ 3.3v(模拟信…...

arcgis for js实现层叠立体效果

在 Web 开发中&#xff0c;利用 ArcGIS for JS 实现一些炫酷的地图效果能够极大地提升用户体验。本文将详细介绍如何使用 ArcGIS for JS 实现层叠立体效果&#xff0c;并展示最终的效果图。 效果图 实现思路 要实现层叠立体效果&#xff0c;关键在于获取边界图形的坐标&#xf…...

多模态本地部署和ollama部署Llama-Vision实现视觉问答

文章目录 一、模型介绍二、预期用途1. 视觉问答(VQA)与视觉推理2. 文档视觉问答(DocVQA)3. 图像字幕4. 图像-文本检索5. 视觉接地 三、本地部署1. 下载模型2. 模型大小3. 运行代码 四、ollama部署1. 安装ollama2. 安装 Llama 3.2 Vision 模型3. 运行 Llama 3.2-Vision 五、效果…...

【DeepSeek】deepseek可视化部署

目录 1 -> 前文 2 -> 部署可视化界面 1 -> 前文 【DeepSeek】DeepSeek概述 | 本地部署deepseek 通过前文可以将deepseek部署到本地使用&#xff0c;可是每次都需要winR输入cmd调出命令行进入到命令模式&#xff0c;输入命令ollama run deepseek-r1:latest。体验很…...

【Git版本控制器】:第一弹——Git初识,Git安装,创建本地仓库,初始化本地仓库,配置config用户名,邮箱信息

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux网络编程 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 ​ 相关笔记&#xff1a; https://blog.csdn.net/dj…...

Fabric.js、leaferjs、pixi.js 库的对比分析

文章目录 一、引言二、参与对比的 canvas 库简介三、性能对比四、易用性对比五、功能特性对比六、综合评价与使用建议七、总结 在前端开发中&#xff0c;canvas 库为实现丰富的图形效果和交互功能提供了强大的支持。本文将对 Fabric.js、leaferjs 和 pixi.js 这三个常见的 canv…...

JVM——堆的回收:引用计数发和可达性分析法、五种对象引用

目录 引用计数法和可达性分析法 引用计数法&#xff1a; 可达性分析算法&#xff1a; 五种对象引用 软引用&#xff1a; 弱引用&#xff1a; 引用计数法和可达性分析法 引用计数法&#xff1a; 引用计数法会为每个对象维护一个引用计数器&#xff0c;当对象被引用时加1&…...

2.11 sqlite3数据库【数据库的相关操作指令、函数】

练习&#xff1a; 将 epoll 服务器 客户端拿来用 客户端&#xff1a;写一个界面&#xff0c;里面有注册登录 服务器&#xff1a;处理注册和登录逻辑&#xff0c;注册的话将注册的账号密码写入数据库&#xff0c;登录的话查询数据库中是否存在账号&#xff0c;并验证密码是否正确…...

开源模型应用落地-Qwen1.5-MoE-A2.7B-Chat与vllm实现推理加速的正确姿势(一)

一、前言 在人工智能技术蓬勃发展的当下,大语言模型的性能与应用不断突破边界,为我们带来前所未有的体验。Qwen1.5-MoE-A2.7B-Chat 作为一款备受瞩目的大语言模型,以其独特的架构和强大的能力,在自然语言处理领域崭露头角。而 vllm 作为高效的推理库,为模型的部署与推理提…...

相得益彰,Mendix AI connector 秒连DeepSeek ,实现研发制造域场景

在当今快速发展的科技领域&#xff0c;低代码一体化平台已成为企业数字化转型的关键工具&#xff0c;同时&#xff0c;大型语言模型&#xff08;LLM&#xff09;如 DeepSeek 在自动生成代码和提供智能建议方面表现出色。 Mendix 于近期发布的 GenAI 万能连接器&#xff0c;目前…...

英语笔记【一】词性

一、be 动词 be 动词&#xff0c;是英语中的一种词汇用法&#xff0c;一般用来表示“是”的意思&#xff0c;也可表示“成为”的意思。 be动词的用法有多种变化形式。英语的句子必有一个动词。be 动词自然也是动词的一种。 am 用于第一人称单数&#xff1b;is 第三人称单数&a…...

同为科技智能PDU助力Deepseek人工智能和数据交互的快速发展

1 2025开年&#xff0c;人工智能领域迎来了一场前所未有的变革。Deepseek成为代表“东方力量”的开年王炸&#xff0c;不仅在国内掀起了技术热潮&#xff0c;并且在全球范围内引起了高度关注。Deepseek以颠覆性技术突破和现象级应用场景席卷全球&#xff0c;这不仅重塑了产业格…...

.NET Web-静态文件访问目录浏览

一、Web根目录访问 创建wwwroot文件夹app.UseStaticFiles(); // 启⽤静态⽂件中间件url/路径 进行访问 二、Web根目录之外的文件 app.UseStaticFiles(new StaticFileOptions {FileProvider new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath,&qu…...