过滤器和监听器
1、过滤器Filter
作用是防止SQL注入、参数过滤、防止页面攻击、空参数矫正、Token校验、Session验证、点击率统计等等;
使用Filter的步骤
- 新建类,实现Filter抽象类;
- 重写init、doFilter、destroy方法;
- 在SpringBoot入口中添加注解@ServletComponentScan,以注册Filter;
注意:通过@Order注解设置过滤器的执行顺序,越小的越先被执行;
import org.springframework.core.annotation.Order;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;/*** @ClassName: FilterDemo* @Author: 中都* @Date: 2021/12/29 22:11* @Description: 过滤器*/
@Order(1)
@WebFilter(filterName = "FilterDemo",urlPatterns = "/*")
public class FilterDemo implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("初始化逻辑,服务器启动时调用");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("拦截器");filterChain.doFilter(servletRequest,servletResponse);}@Overridepublic void destroy() {System.out.println("销毁逻辑,服务器关闭时调用");}
}
@ServletComponentScan
@SpringBootApplication
public class SpringbootstudyApplication {public static void main(String[] args) {SpringApplication.run(SpringbootstudyApplication.class, args);}}


示例代码:
/*** @Author: zhondu* @Date: 2023/1/25 18:36* @Desc: 过滤器*/
@Component
public class LogFilter implements Filter {public static final Logger logger = LoggerFactory.getLogger(LogFilter.class);@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// filterChain是过滤器执行链,因为可以有多个过滤器的// 打印请求信息HttpServletRequest request = (HttpServletRequest) servletRequest;logger.info("-----------LogFilter 开始--------------");// 接口和方法类型(get post)logger.info("请求地址:{} {}", request.getRequestURL().toString(), request.getMethod());logger.info("远程地址:{}", request.getRemoteAddr());// 还可以打印其他很多信息,请求头之类的,因为这里拿到的是整个requestlong startTime = System.currentTimeMillis();filterChain.doFilter(servletRequest, servletResponse);logger.info("-----------LogFilter 结束 耗时:{} ms--------------", System.currentTimeMillis() - startTime);}
}
** 执行结果 **

2、监听器
监听对象的增删改查等操作,然后做出相应处理,用户统计在线人数、在线用户、系统加载时的信息初始化等等;
/*** @Author: zhondu* @Date: 2023/1/26 10:18* @Desc: 拦截器 Spring特有的,常用于登录校验 权限校验 请求日志打印*/
@Component
public class LogInterceptor implements HandlerInterceptor {public static final Logger logger = LoggerFactory.getLogger(LogInterceptor.class);/*** 拦截器 -- 请求进入方法之前的拦截处理* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {logger.info("-----------LogInterceptor 开始--------------");// 接口和方法类型(get post)logger.info("请求地址:{} {}", request.getRequestURL().toString(), request.getMethod());logger.info("远程地址:{}", request.getRemoteAddr());long startTime = System.currentTimeMillis();request.setAttribute("requestStartTime",startTime);// 返回true 才会继续走,否则就直接结束了,所以可以用于 登录校验 权限校验return true;}/*** 拦截器 -- 走完方法之后返回前端的拦截处理* @param request* @param response* @param handler* @param modelAndView* @throws Exception*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {long startTime = (Long) request.getAttribute("requestStartTime");logger.info("-----------LogInterceptor 结束 耗时:{} ms--------------", System.currentTimeMillis() - startTime);}
}
拦截器还需要加一个全局配置的:
import com.zhondu.wiki.interceptor.LogInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import javax.annotation.Resource;/*** @Author: zhondu* @Date: 2023/1/26 10:26* @Desc:*/
@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {@Resourceprivate LogInterceptor logInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 增加过滤器 -- 针对所有的请求 (但是例如登录校验就不是所有的接口都需要校验,例如登录校验是不能校验登录接口本身的)registry.addInterceptor(logInterceptor).addPathPatterns("/**") // 针对所有的请求.excludePathPatterns("/login"); // 排除掉登录请求-不拦截}
}

拦截器分为前后两个方法,过滤器只有一个,而且过滤器是容器级别的(Tomcat netty等),拦截器是应用级别的,例如web应用
3、AOP
AOP也可以打印参数相关的信息,但是与过滤器拦截器不同,他依靠的不是request,而是连接点JoinPoint,
需要引入依赖:
<!--AOP--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.70</version></dependency>
package com.zhondu.wiki.aspect;import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.support.spring.PropertyPreFilters;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;/*** @Author: zhondu* @Date: 2023/1/26 11:49* @Desc: AOP*/
@Aspect
@Component
public class LogAspect {public static final Logger logger = LoggerFactory.getLogger(LogAspect.class);// 定义一个切点 监控所有的controller@Pointcut("execution(public * com.zhondu.*.controller..*Controller.*(..))")public void controllerPointcut() {}// 前置通知@Before("controllerPointcut()")public void doBefore(JoinPoint joinPoint) throws Throwable {// 开始打印请求日志ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();Signature signature = joinPoint.getSignature();String name = signature.getName();// 打印请求信息logger.info("------------- 开始 -------------");logger.info("请求地址: {} {}", request.getRequestURL().toString(), request.getMethod());logger.info("类名方法: {}.{}", signature.getDeclaringTypeName(), name);logger.info("远程地址: {}", request.getRemoteAddr());// 打印请求参数Object[] args = joinPoint.getArgs();// LOG.info("请求参数: {}", JSONObject.toJSONString(args));Object[] arguments = new Object[args.length];for (int i = 0; i < args.length; i++) {if (args[i] instanceof ServletRequest|| args[i] instanceof ServletResponse|| args[i] instanceof MultipartFile) {continue;}arguments[i] = args[i];}// 排除字段,敏感字段或太长的字段不显示String[] excludeProperties = {"password", "file"};PropertyPreFilters filters = new PropertyPreFilters();PropertyPreFilters.MySimplePropertyPreFilter excludefilter = filters.addFilter();excludefilter.addExcludes(excludeProperties);logger.info("请求参数: {}", JSONObject.toJSONString(arguments, excludefilter));}/*** 环绕通知* @param proceedingJoinPoint* @return* @throws Throwable*/@Around("controllerPointcut()")public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {long startTime = System.currentTimeMillis();Object result = proceedingJoinPoint.proceed();// 排除字段,敏感字段或太长的字段不显示String[] excludeProperties = {"password", "file"};PropertyPreFilters filters = new PropertyPreFilters();PropertyPreFilters.MySimplePropertyPreFilter excludefilter = filters.addFilter();excludefilter.addExcludes(excludeProperties);logger.info("返回结果: {}", JSONObject.toJSONString(result, excludefilter));logger.info("------------- 结束 耗时:{} ms -------------", System.currentTimeMillis() - startTime);return result;}
}

### 区别:

相关文章:
过滤器和监听器
1、过滤器Filter 作用是防止SQL注入、参数过滤、防止页面攻击、空参数矫正、Token校验、Session验证、点击率统计等等; 使用Filter的步骤 新建类,实现Filter抽象类;重写init、doFilter、destroy方法;在SpringBoot入口中添加注解…...
Acwing 第 91 场周赛
Powered by:NEFU AB-IN B站直播录像! Link 文章目录Acwing 第 91 场周赛A AcWing 4861. 构造数列题意思路代码B AcWing 4862. 浇花题意思路代码C AcWing 4863. 构造新矩阵题意思路代码Acwing 第 91 场周赛 A AcWing 4861. 构造数列 题意 略 思路 将每个数的每一位…...
JavaEE|套接字编程之UDP数据报
文章目录一、DatagramSocket API构造方法常用方法二、DatagramPacket API构造方法常用方法E1:回显服务器的实现E2:带有业务逻辑的请求发送一、DatagramSocket API 在操作系统中,把socket对象当成了一个文件处理。等价于是文件描述符表上的一项。 普通的文件…...
如何使用Python创建一个自定义视频播放器
目录 1、安装vlc的64位版本。 2、安装python的vlc模块。 3、编写如下代码,包含了播放,暂停,停止、音量控制功能。 4、来看一看运行结果。 5、如果遇到播放不了的问题,解决方式如下: 这个例子使用VLC作为视频播放器…...
Elasticsearch进行优化-使用索引拆分(Split)和索引收缩(shrink )
一、索引拆分和收缩的场景 在Elasticsearch集群部署的初期我们可能评估不到位,导致分配的主分片数量太少,单分片的数据量太大,导致搜索时性能下降,这时我们可以使用Elasticsearch提供的Split功能对当前的分片进行拆分,…...
数论 —— 高斯记号(Gauss mark)
定义 数学上,高斯记号(Gauss mark)是指对取整符号和取小符号的统称,用于数论等领域。 设 x∈Rx \in \textbf{R}x∈R,用 [x][x][x] 表示不超过 xxx 的最大整数。也可记作 [x][x][x]。设 x∈Rx \in \textbf{R}x∈R&…...
【随笔】程序员眼中的 CPU,“没有灵魂的躯体”
引言 先引用一段比较有意思的论述: 现实中每个人是由两部分构成,灵魂和躯体,灵魂依附于躯体游走于世间,现实中我们面对的每个人其实面对的是其灵魂而非肉体,肉体不过是表象而已。 灵魂本性乃一恶物,寄生于…...
算法的时间复杂度
算法在编写成可执行程序后,运行时需要消耗时间资源和空间(内存)资源,因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的。 时间复杂度主要衡量一个算法运行的快慢,而空间复杂度主要衡量一个算法运…...
华为OD机试 - 叠放书籍(Python) | 机试题算法思路 【2023】
最近更新的博客 华为OD机试 - 寻找路径 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - 五键键盘 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - IPv4 地址转换成整数 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试 - 对称美学 | 备考思路,刷题要点,答疑 …...
进程间通信(重点)
概念 进程是一个独立的资源分配单元,不同进程之间的资源是独立的进程并非孤立的,不同进程需要进行信息的交互和状态的传递,因此需要进程之间的通信【IPC: Inter processes communication】 如qq聊天,qq在每个人的手机上是独立的…...
Reverse入门[不断记录]
文章目录前言一、[SWPUCTF 2021 新生赛]re1二、[SWPUCTF 2021 新生赛]re2三、[GFCTF 2021]wordy[花指令]四、[NSSRound#3 Team]jump_by_jump[花指令]五、[NSSRound#3 Team]jump_by_jump_revenge[花指令]前言 心血来潮,想接触点Reverse,感受下Reverse&am…...
如何实现外网访问内网ip?公网端口映射或内网映射来解决
本地搭建服务器应用,在局域网内可以访问,但在外网不能访问。如何实现外网访问内网ip?主要有两种方案:路由器端口映射和快解析内网映射。根据自己本地网络环境,结合是否有公网IP,是否有路由权限,…...
[acwing周赛复盘] 第 91 场周赛20230218
[acwing周赛复盘] 第 91 场周赛20230218 一、本周周赛总结二、 4861. 构造数列1. 题目描述2. 思路分析3. 代码实现三、4862. 浇花1. 题目描述2. 思路分析3. 代码实现四、4863. 构造新矩阵1. 题目描述2. 思路分析3. 代码实现六、参考链接一、本周周赛总结 这周挺难的。T1 贪心分…...
蓝桥12届
小蓝准备用 256MB 的内存空间开一个数组,数组的每个元素都是 32 位 二进制整数,如果不考虑程序占用的空间和维护内存需要的辅助空间,请问 256MB 的空间可以存储多少个 32 位二进制整数?1MB 1024KB 1KB 1024字节(byte) 1字节 8位…...
华为OD机试 - 斗地主(JS)
斗地主 题目 斗地主起源于湖北十堰房县, 据传是一位叫吴修全的年轻人根据当地流行的扑克玩法“跑得快”改编的, 如今已风靡整个中国,并流行于互联网上 牌型: 单顺,又称顺子,最少5张牌,最多12张牌(3...A),不能有2, 也不能有大小王,不计花色 例如:3-4-5-7-8,7-8-9-1…...
【MyBatis】| MyBatis的注解式开发
目录 一:MyBatis的注解式开发 1. Insert注解 2. Delete注解 3. Update注解 4. Select注解 5. Results注解 一:MyBatis的注解式开发 MyBatis中也提供了注解式开发⽅式,采⽤注解可以减少Sql映射⽂件的配置。 当然,使⽤注…...
python自制PDF转换.PNG格式图片(按每页生成图片完整源码)小工具!
使用PyQt5应用程序制作PDF转换成图片的小工具,可以导入PDF文档后一键生成对应的PNG图片。 PDF图片转换小工具使用的中间件: python版本:3.6.8 UI应用版本:PyQt5 PDF文件操作非标准库:PyPDF2 PNG图片生成库࿱…...
Go 数组和切片反思
切片的底层数据结构是数组,所以,切片是基于数组的上层封装,使用数组的场景,也完全可以使用切片。 类型比较 我看到 go 1.17 有对切片和数组转换的优化,禁不住纳闷,有什么场景是必须数组来完成的呢&#x…...
win10电脑性能优化设置
win10电脑性能优化设置 目录win10电脑性能优化设置1.桌面图标显示2.wini2.1 “系统”2.1.1专注助手 关2.1.2 电源和睡眠 设置为从不2.1.3 存储 开2.2 网络和Internet2.3 个性化2.4 应用2.5 账户2.6 游戏2.7 隐私墨迹书写和键入个性化:关活动历史记录:全部…...
作为初学者必须要了解的几种常用数据库!
现在已经存在了很多优秀的商业数据库,如甲骨文(Oracle)公司的 Oracle 数据库、IBM 公司的 DB2 数据库、微软公司的 SQL Server 数据库和 Access 数据库。同时,还有很多优秀的开源数据库,如 MySQL 数据库,Po…...
LeetCode 2946. 循环移位后的矩阵相似检查【数学周期性+原地比较】简单
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...
FLUX.1-dev像素生成器效果对比:不同Scale值对像素结构强度影响实测
FLUX.1-dev像素生成器效果对比:不同Scale值对像素结构强度影响实测 1. 像素艺术生成技术概述 像素幻梦(Pixel Dream Workshop)是基于FLUX.1-dev扩散模型构建的专业像素艺术生成工具。它采用16-bit现代明亮风格设计,为创作者提供…...
Java面试如何突击?核心知识点有哪些?该如何准备拿下offer?
一、Java 面试核心知识点(按考察优先级排序)1. Java 基础面向对象:封装、继承、多态(重载与重写)、抽象类与接口的区别。String 系列:String 不可变性、StringBuilder 与 StringBuffer 的区别、常量池。集合…...
Qwen3.5-4B-Claude-Opus垂直场景:工业IoT设备告警根因的多条件推演
Qwen3.5-4B-Claude-Opus垂直场景:工业IoT设备告警根因的多条件推演 1. 工业IoT告警分析的挑战与机遇 在现代工业物联网环境中,设备告警分析面临着前所未有的复杂性。一个典型的制造工厂可能同时运行着数千台联网设备,每天产生数以万计的告警…...
Nginx反向代理实战:不改代码轻松解决前后端跨域问题(附完整配置模板)
Nginx反向代理实战:不改代码轻松解决前后端跨域问题(附完整配置模板) 前后端分离架构已成为现代Web开发的主流模式,但随之而来的跨域问题却让不少开发者头疼。想象一下这样的场景:你的前端运行在https://frontend.com&…...
Repomix用户体验:CLI界面设计与交互的终极指南
Repomix用户体验:CLI界面设计与交互的终极指南 【免费下载链接】repomix 📦 Repomix (formerly Repopack) is a powerful tool that packs your entire repository into a single, AI-friendly file. Perfect for when you need to feed your codebase t…...
游戏玩家如何选?网易UU/ToDesk远程控制延迟实测(含手机投屏技巧)
游戏玩家专属远程控制工具深度评测:延迟、画质与投屏技巧全解析 作为一名资深游戏玩家,你是否遇到过这样的场景:出差在外想用手机继续刷副本,却苦于找不到合适的远程控制方案;或是想在平板上玩PC独占的3A大作ÿ…...
从0到1:Java+AI入门实战,看完直接上手项目
文章目录前言环境准备:别急着装Python,先把JDK升到21第一滴血:让Java程序说出"人话"进阶玩法:给AI装上"记忆"和"工具"让AI记住你们聊过啥让AI能查数据库、调接口实战项目:搭建私有知识库…...
Flutter 实现点击任意位置收起键盘的最佳实践
痛点 在 Flutter 开发中,TextField 聚焦后会弹出键盘,关闭键盘通常需要: 点击系统返回键点击输入框外的空白区域(但很多情况下点击空白区域也没反应)点击其他输入框(键盘会切换到另一个输入框,不…...
Simulink频域分析避坑指南:如何准确获取谐振频率(含MATLAB代码)
Simulink频域分析实战:谐振频率精准提取方法论与MATLAB实现 在控制系统设计与分析领域,频域特性是评估系统动态性能的核心指标之一。而谐振频率作为频域响应中的关键特征点,直接影响着系统的稳定性和响应速度。然而,许多工程师在使…...
