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

Springboot——自定义Filter使用测试总结

文章目录

  • 前言
  • 自定义过滤器并验证
  • 关于排除某些请求的方式
  • 创建测试接口
  • 请求测试
  • 验证异常过滤器的执行流程
  • 注意事项
  • 资料参考

前言

在Java-web的开发领域,对于过滤器拦截器用处还是很多,但两者的概念却极易混淆。

过滤器拦截器都是采用AOP的核心思想,对具体的实现方法进行增强,都能拦截请求方法。

不同点过滤器拦截器
研发者由Servlet研发由SpringMVC研发
拦截对象拦截WEB请求拦截器不仅可以拦截请求,还能拦截普通方法。
执行顺序过滤器会比拦截器优先执行拦截器在过滤器之后执行,但使用比过滤器简单。
使用场景编码格式转化跨域解决xss攻击权限控制、日志打印、参数验证、回话信息等。

【资料参考】

  • 过滤器和拦截器的异同(小计)
  • springboot配置监听器、过滤器和拦截器

以实际生活中的栗子,作为各个名词的描述:

  • 过滤器 过滤器好比就是筛子,只有满足大小要求的颗粒,才能通过过滤器,不满足的则会筛出来。
  • 拦截器 拦截器就好比是一个门户,只能满足要求,才能进入

这两者本身上其实都差不多,只是在技术层面为了区别各个不同的原理和技术,才定义了不同的名词。

本篇博客不说拦截器,只说过滤器的使用和基本准则。

自定义过滤器并验证

创建Springboot项目,并创建两个自定义的过滤器,如下所示:

  • MyFilter1
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;@Slf4j
@Order(1) // 数字越小  优先级越高
@WebFilter(filterName = "myFilter1",urlPatterns = {"/*"})
public class MyFilter1 implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {log.info("####  MyFilter1 ==== init ####");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {log.info("####  MyFilter1 ==== doFilter ####");log.info("####  MyFilter1 ==== doFilter before ####");chain.doFilter(request,response);log.info("####  MyFilter1 ==== doFilter after ####");}@Overridepublic void destroy() {log.info("####  MyFilter1 ==== destroy ####");}
}
  • MyFilter2
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;@Slf4j
@Order(2) // 数字越小  优先级越高
@WebFilter(filterName = "myFilter2",urlPatterns = {"/*"}) // urlPatterns 设置需要拦截过滤的请求,可以正则表达式,未指定时会拦截所有请求
public class MyFilter2 implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {log.info("####  MyFilter2 ==== init ####");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {log.info("####  MyFilter2 ==== doFilter ####");log.info("####  MyFilter2 ==== doFilter before ####");String msg = request.getParameter("msg");if("err".equalsIgnoreCase(msg)){throw new RuntimeException("传递参数有误,验证过滤器....");}chain.doFilter(request,response);log.info("####  MyFilter2 ==== doFilter after ####");}@Overridepublic void destroy() {log.info("####  MyFilter2 ==== destroy ####");}
}

可以看到本次使用的是注解方式,除了新增这两个自定义的Filter之外,还需要在启动类上增加一个注解标识,否则自定义的过滤器并不会被加载,如下所示:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;@SpringBootApplication
@ServletComponentScan // 扫描filter
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class,args);}
}

@ServletComponentScan // 扫描filter

在自定义的过滤器中,使用的@WebFilter注解方式,该注解中需要设定某些值,这些参数信息又有什么含义呢?

参数名含义
filterName给过滤器定义别名称,需要唯一区别。
urlPatterns过滤器针对的请求url路径,默认或者不配置时,是过滤所有的请求。此处可以写正则表达式。
initParams自定义过滤器初始化参数的数组,此参数可以通过自定义过滤器 init() 的入参FilterConfig对象的 getInitParameter() 方法获取;(由于过滤器没有直接排除自定义URL不拦截的设定,如果我们需要在自定义拦截的URL中排除部分不需要拦截的URL,可以通过将需要排除的URL放到initParams参数中再在doFilter方法中排除)

关于排除某些请求的方式

参考:SpringBoot自定义过滤器Filter使用详解

其中,有这么一个栗子,如下所示:

@WebFilter(filterName = "testFilter", urlPatterns = "/*", initParams = @WebInitParam(name = "noFilterUrl", value = "/test")) // 给定初始化参数
public class TestFilter implements Filter {private List<String> noFilterUrls; @Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 从过滤器配置中获取initParams参数String noFilterUrl = filterConfig.getInitParameter("noFilterUrl");// 将排除的URL放入成员变量noFilterUrls中if (StringUtils.isNotBlank(noFilterUrl)) {noFilterUrls = new ArrayList<>(Arrays.asList(noFilterUrl.split(",")));}}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)throws IOException, ServletException {// 过滤器配置的  urlPatterns  为 /* 表示过滤所有的请求// 有请求进来时,会先进入到过滤器中,此时则获取请求的uri地址String url = ((HttpServletRequest)servletRequest).getRequestURI();Boolean flag = false;if (!CollectionUtils.isEmpty(noFilterUrls)) {for (String noFilterUrl : noFilterUrls) {// 如果请求的地址中包含有 initParams 传递的参数值,则不继续向下执行if (url.contains(noFilterUrl)) {flag = true;break;}}}if (!flag) {......	//过滤请求响应逻辑} // 继续向下执行,调用该方法filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {}
}

感叹这个作者的奇妙思维方式!

创建测试接口

回归正题,创建上面两个自定义的过滤器之后,还需要创建一个测试接口,如下所示:

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/test1")
@Api(tags = "测试控制器  1")
@Slf4j
public class TestController {@PostMapping("/demo1")@ApiOperation("demo1")public String demo1(){log.info("请求被调用了!!!!!");return "demo 1 .....";}
}

启动项目观察控制台打印。
在这里插入图片描述

这里的顺序是加在时的顺序,并不是@Order(int) 设定的原因!

请求测试

清空控制台的日志信息,请求测试接口,观察控制台日志输出情况,如下所示:
在这里插入图片描述
在这里插入图片描述

通过调用自定义过滤器filter的日志打印,可以很清楚的了解到请求的执行过程。如下所示:
在这里插入图片描述
由最开始的客户端请求–》MyFilter1–》MyFilter2–》指定的controller–》MyFilter2–》MyFilter1–》客户端。闭环操作。

这里为什么是MyFilter1MyFilter2之前,根本原因就是定义filter时,设定了@Order(1)给定了优先级。

数字越小,优先级越高!

验证异常过滤器的执行流程

MyFilter2中,给定了请求参数 msg=err时抛出异常。

出现异常了,后面的filter还会继续执行不?接下来再次进行请求测试:
在这里插入图片描述
查看控制台,观察日志信息,如下所示:
在这里插入图片描述
在执行到MyFilter1MyFilter2后,由于MyFilter1中抛出了异常,还没有执行对应的chain.doFilter(request,response);后续的链路,所以日志在此处戛然而止!

出现异常后,并不会继续执行后续的filter!

注意事项

自定义的Filter类上,不要添加 @Component 注解,不然会导致程序启动报错,启动不成功
在这里插入图片描述

资料参考

SpringBoot自定义过滤器Filter使用详解

这个大佬博客中给出了第二种方式,但总感觉哪里有问题,关于第二种方式的配置操作,可以参考下列资料:

springboot 自定义过滤器

相关文章:

Springboot——自定义Filter使用测试总结

文章目录前言自定义过滤器并验证关于排除某些请求的方式创建测试接口请求测试验证异常过滤器的执行流程注意事项资料参考前言 在Java-web的开发领域&#xff0c;对于过滤器和拦截器用处还是很多&#xff0c;但两者的概念却极易混淆。 过滤器和拦截器都是采用AOP的核心思想&am…...

软件测试(进阶篇)(1)

一)如何根据需求来设计测试用例&#xff1f; 1)验证功能的正确性&#xff0c;合理性&#xff0c;无二义性&#xff0c;逻辑要正确 2)分析需求&#xff0c;细化需求&#xff0c;从需求中提取出测试项&#xff0c;根据测试项找到测试点&#xff0c;根据测试点具体的来进行设计测试…...

(七十三)大白话深入探索多表关联的SQL语句到底是如何执行的?(1)

今天我们来继续跟大家聊聊多表关联语句是如何执行的这个问题&#xff0c;上次讲了一个最最基础的两个表关联的语句和执行过程&#xff0c;其实今天我们稍微来复习一下&#xff0c;然后接着上次的内容&#xff0c;引入一个“内连接”的概念来。 假设我们有一个员工表&#xff0…...

SYSU程设c++(第三周) 对象类、类的成员、类与结构体的区别、类的静态成员

对象&类 类用于指定对象的形式&#xff0c;它包含数据的表示方法和用于处理数据的方法。 • 类中的数据和方法称为类的成员。 • 函数在一个类中也被称为类的成员。 定义一个类&#xff0c;其效果是定义一个数据类型的蓝图。它定义了类的对象包括了什么&#xff0c;以及可…...

Redis管道

目录 1、什么是管道&#xff1f; 2、案例演示 3、注意事项 4、面试题 1、什么是管道&#xff1f; 管道&#xff08;pipeline&#xff09;可以一次性发送多条命令给服务端&#xff0c;服务端依次处理完&#xff0c;通过一条响应一次性将结果返回&#xff0c;减少 IO 的次数&…...

conda的共用package[硬链接]@pytorch和tensorflow装在同一个环境里好不好?

文章目录refpackage复用(指定同版本)conda install 比pip install 更可能节省空间pytorch和tensorflow装在同一个环境里?导入依赖导入依赖试验ref python - Can packages be shared across Anaconda environments? - Stack OverflowManaging environments — conda 23.1.0.p…...

「Vue面试题」动态给vue的data添加一个新的属性时会发生什么?怎样去解决的?

一、直接添加属性的问题 我们从一个例子开始 定义一个p标签&#xff0c;通过v-for指令进行遍历 然后给botton标签绑定点击事件&#xff0c;我们预期点击按钮时&#xff0c;数据新增一个属性&#xff0c;界面也 新增一行 <p v-for"(value,key) in item" :key&q…...

Flutter-Scaffold组件

在Flutter开发当中&#xff0c;我们可能会遇到以下的需求&#xff1a;实现页面组合使用&#xff0c;比如说有悬浮按钮、顶部菜单栏、左右抽屉侧边栏、底部导航栏等等效果。Scaffold组件可以帮我们实现上面需求说的效果。这篇博客主要分享容器组件的Scaffold组件的使用&#xff…...

Postman简介及接口测试流程(小菜鸟攻略)

目录 前言 一、常见接口 二、前端和后端 三、什么是接口测试 四、接口组成 1、接口说明 2、调用url 3、请求方法&#xff08;get\post&#xff09; 4、请求参数、参数类型、请求参数说明 5、返回参数说明 五、为什么要做接口测试 本章主要介绍如何使用postman做接口…...

kubebuilder注释

标记语法Empty kubebuilder:validation:Optional&#xff1a;空标记像命令行中的布尔标记位-- 仅仅是指定他们来开启某些行为。Anonymous kubebuilder:validation:MaxItems2&#xff1a;匿名标记使用单个值作为参数。Multioption kubebuilder:printcolumn:JSONPath".statu…...

java日志

日志是软件开发的重要组成部分。一个精心编写的日志代码提供快速的调试&#xff0c;维护方便&#xff0c;以及应用程序的运行时信息结构化存储。日志记录确实也有它的缺点。它可以减缓的应用程序Log4jLog4j是Apache的一个开放源代码项目&#xff0c;通过使用Log4j&#xff0c;我…...

研发中台拆分过程的一些心得总结

背景在 21 年&#xff0c;中台拆分在 21 年&#xff0c;以下为中台拆分的过程心得&#xff0c;带有一定的主观&#xff0c;偏向于中小团队中台建设参考&#xff08;这里的中小团队指 3-100 人的团队&#xff09;&#xff0c;对于大型团队不太适用&#xff0c;毕竟大型团队人中 …...

HTTP介绍

HTTP1、简介HTTP概念&#xff1a;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff0c;规定了浏览器和服务器之间数据传输的规则。数据传输的规则指的是请求数据和响应数据需要按照指定的格式进行传输。如果想知道具体的格式&#xff0c;可以打开浏览器&#xf…...

10 卷积神经网络及python实现

1 卷积神经网络简介 卷积神经网络(Convolutional Neural Network, CNN)由LeCun在上世纪90年代提出。 LeCun Y., Bottou L., Bengio Y., and Haffner P., Gradient-based learning applied to document recognition, Proceedings of the IEEE, pp. 1-7, 1998. 卷积核和特征图&…...

【立体匹配论文阅读】AANet: Adaptive Aggregation Network for Efficient Stereo Matching

Authors: Haofei Xu, Juyong Zhang Link: https://arxiv.org/abs/2004.09548 Years: 2020 Credit Novelty and Question set up 主流的立体匹配模型的代价聚合操作主要用了3D卷积&#xff0c;这部分操作的算力和内存消耗过大&#xff0c;因此作者提出一种新的模型AANet&#x…...

服务器防入侵攻击,安全加固措施

服务器防入侵攻击&#xff0c;安全加固措施当服务器被入侵&#xff0c;被攻击的时候&#xff0c;很多服务器维护人员不懂得如何去防止入侵&#xff0c;防止黑客的攻击&#xff0c;只能眼巴巴的看着服务器被任意的攻击&#xff0c;给服务器上的网站造成严重的经济损失&#xff0…...

解读:“出境标准合同”与“出境安全评估”要点与异同

《数据安全法》第四条及《个人信息保护法》第三章对数据出境、个人信息跨境提出明确要求&#xff0c;《数据安全法》与《个人信息保护法》存在互相包含、被包含、衔接、特性、独立性、相互补充等内涵。本文通过上位法互相衔接、关联、特性的思路&#xff0c;去观察《个人信息出…...

python带你成功复刻热门手机游戏——飞翔的小鸟

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 飞翔的小鸟&#xff08;游戏英文名&#xff1a;Flappy Bird&#xff09; 一款由越南独立开发者开发的手机游戏&#xff0c;是之前非常流行的一款手机游戏 小游戏目标&#xff1a;让小鸟穿过管子&#xff0c;不要碰到任何物体…...

YOLOv8初体验:检测、跟踪、模型部署

安装 YOLOv8有两种安装方式&#xff0c;一种是直接用pip命令安装&#xff1a; pip install ultralytics另外一种是通过源码安装&#xff1a; git clone https://github.com/ultralytics/ultralytics cd ultralytics pip install -e .[dev]安装完成后就可以通过yolo命令在命令…...

Vue 监听(watch handler)

普通监听 缺点&#xff1a;不能深度监听&#xff08;对象属性的改变&#xff09;&#xff0c;刷新或首次加载不能执行。 watch: { carts: function (val, oldVal) { console.log(new: %s, old: %s, val, oldVal) } } 高级监…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...