spring里面内置的非常实用的工具
一 、请求数据记录
Spring Boot提供了一个内置的日志记录解决方案,通过 AbstractRequestLoggingFilter 可以记录请求的详细信息。
AbstractRequestLoggingFilter 有两个不同的实现类,我们常用的是 CommonsRequestLoggingFilter。

通过 CommonsRequestLoggingFilter 开发者可以自定义记录请求的参数、请求体、请求头和客户端信息。
启用方式很简单,加个配置就行了:
@Configuration
public class RequestLoggingConfig {@Beanpublic CommonsRequestLoggingFilter logFilter() {CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();filter.setIncludeQueryString(true);filter.setIncludePayload(true);filter.setIncludeHeaders(true);filter.setIncludeClientInfo(true);filter.setAfterMessagePrefix("REQUEST DATA-");return filter;}
}
接下来需要配置日志级别为 DEBUG,就可以详细记录请求信息:
logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG

二 、请求/响应包装器(多次获取json body参数)
在 Spring Boot 中,请求和响应包装器是用于增强原生 HttpServletRequest 和 HttpServletResponse 对象的功能。这些包装器允许开发者在请求处理过程中拦截和修改请求和响应数据,从而实现一些特定的功能,如请求内容的缓存、修改、日志记录,以及响应内容的修改和增强。
请求包装器
ContentCachingRequestWrapper:这是 Spring 提供的一个请求包装器,用于缓存请求的输入流。它允许多次读取请求体,这在需要多次处理请求数据(如日志记录和业务处理)时非常有用。
响应包装器
ContentCachingResponseWrapper:这是 Spring 提供的一个响应包装器,用于缓存响应的输出流。它允许开发者在响应提交给客户端之前修改响应体,这在需要对响应内容进行后处理(如添加额外的头部信息、修改响应体)时非常有用。
使用场景
- 请求日志记录:在处理请求之前和之后记录请求的详细信息,包括请求头、请求参数和请求体。
- 修改请求数据:在请求到达控制器之前修改请求数据,例如添加或修改请求头。
- 响应内容修改:在响应发送给客户端之前修改响应内容,例如添加或修改响应头,或者对响应体进行签名。
- 性能测试:通过缓存请求和响应数据,可以进行性能测试,而不影响实际的网络 I/O 操作。
具体用法
请求包装器的使用
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Component
public class RequestWrapperFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);// 可以在这里处理请求数据byte[] body = requestWrapper.getContentAsByteArray();// 处理body,例如记录日志//。。。filterChain.doFilter(requestWrapper, response);}
}
响应包装器的使用
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Component
public class ResponseWrapperFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);filterChain.doFilter(request, responseWrapper);// 可以在这里处理响应数据byte[] body = responseWrapper.getContentAsByteArray();// 处理body,例如添加签名responseWrapper.setHeader("X-Signature", "some-signature");// 必须调用此方法以将响应数据发送到客户端responseWrapper.copyBodyToResponse();}
}
在上面的案例中,OncePerRequestFilter 确保过滤器在一次请求的生命周期中只被调用一次,这对于处理请求和响应数据尤为重要,因为它避免了在请求转发或包含时重复处理数据。
通过使用请求和响应包装器,开发者可以在不改变原有业务逻辑的情况下,灵活地添加或修改请求和响应的处理逻辑。
三、单次过滤器
3.1 OncePerRequestFilter
OncePerRequestFilter 是 Spring 框架提供的一个过滤器基类,它继承自 Filter 接口。这个过滤器具有以下特点:
- 单次执行:
OncePerRequestFilter确保在一次请求的生命周期内,无论请求如何转发(forwarding)或包含(including),过滤器逻辑只执行一次。这对于避免重复处理请求或响应非常有用。 - 内置支持:它内置了对请求和响应包装器的支持,使得开发者可以方便地对请求和响应进行包装和处理。
- 简化代码:通过继承
OncePerRequestFilter,开发者可以减少重复代码,因为过滤器的执行逻辑已经由基类管理。 - 易于扩展:开发者可以通过重写
doFilterInternal方法来实现自己的过滤逻辑,而不需要关心过滤器的注册和执行次数。
3.2 OncePerRequestFilter 使用场景
- 请求日志记录:在请求处理之前和之后记录请求的详细信息,如请求头、请求参数和请求体,而不希望在请求转发时重复记录。
- 请求数据修改:在请求到达控制器之前,对请求数据进行预处理或修改,例如添加或修改请求头,而不希望这些修改在请求转发时被重复应用。
- 响应数据修改:在响应发送给客户端之前,对响应数据进行后处理或修改,例如添加或修改响应头,而不希望这些修改在请求包含时被重复应用。
- 安全控制:实现安全控制逻辑,如身份验证、授权检查等,确保这些逻辑在一次请求的生命周期内只执行一次。
- 请求和响应的包装:使用
ContentCachingRequestWrapper和ContentCachingResponseWrapper等包装器来缓存请求和响应数据,以便在请求处理过程中多次读取或修改数据。 - 性能监控:在请求处理前后进行性能监控,如记录处理时间,而不希望这些监控逻辑在请求转发时被重复执行。
- 异常处理:在请求处理过程中捕获和处理异常,确保异常处理逻辑只执行一次,即使请求被转发到其他处理器。
通过使用 OncePerRequestFilter,开发者可以确保过滤器逻辑在一次请求的生命周期内只执行一次,从而避免重复处理和潜在的性能问题。这使得 OncePerRequestFilter 成为处理复杂请求和响应逻辑时的一个非常有用的工具。
四 AOP 三件套
在 Spring 框架中,AOP(面向切面编程)是一个强大的功能,它允许开发者在不修改源代码的情况下,对程序的特定部分进行横向切入。AopContext、AopUtils 和 ReflectionUtils 是 Spring AOP 中提供的几个实用类。
我们一起来看下。
4.1 AopContext
AopContext 是 Spring 框架中的一个类,它提供了对当前 AOP 代理对象的访问,以及对目标对象的引用。
AopContext 主要用于获取当前代理对象的相关信息,以及在 AOP 代理中进行一些特定的操作。
常见方法有两个:
getTargetObject(): 获取当前代理的目标对象。currentProxy(): 获取当前的代理对象。
其中第二个方法,在防止同一个类中注解失效的时候,可以通过该方法获取当前类的代理对象。
举个栗子:
public void noTransactionTask(String keyword){ // 注意这里 调用了代理类的方法((YourClass) AopContext.currentProxy()).transactionTask(keyword);
}@Transactional
void transactionTask(String keyword) {try {Thread.sleep(5000);} catch (InterruptedException e) { //logger//error tracking}System.out.println(keyword);
}
同一个类中两个方法,noTransactionTask 方法调用 transactionTask 方法,为了使事务注解不失效,就可以使用 AopContext.currentProxy() 去获取当前代理对象。
4.2 AopUtils
AopUtils 提供了一些静态方法来处理与 AOP 相关的操作,如获取代理对象、获取目标对象、判断代理类型等。
常见方法有三个:
getTargetObject(): 从代理对象中获取目标对象。isJdkDynamicProxy(Object obj): 判断是否是 JDK 动态代理。isCglibProxy(Object obj): 判断是否是 CGLIB 代理。
举个栗子:
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.support.AopUtils;public class AopUtilsExample {public static void main(String[] args) {MyService myService = ...// 假设 myService 已经被代理if (AopUtils.isCglibProxy(myService)) {System.out.println("这是一个 CGLIB 代理对象");}}
}
4.3 ReflectionUtils
ReflectionUtils 提供了一系列反射操作的便捷方法,如设置字段值、获取字段值、调用方法等。这些方法封装了 Java 反射 API 的复杂性,使得反射操作更加简单和安全。
常见方法:
makeAccessible(Field field): 使私有字段可访问。getField(Field field, Object target): 获取对象的字段值。invokeMethod(Method method, Object target, Object... args): 调用对象的方法。
举个栗子:
import org.springframework.util.ReflectionUtils;import java.lang.reflect.Field;
import java.util.Map;public class ReflectionUtilsExample {public static void main(String[] args) throws Exception {ExampleBean bean = new ExampleBean();bean.setMapAttribute(new HashMap<>());Field field = ReflectionUtils.findField(ExampleBean.class, "mapAttribute");ReflectionUtils.makeAccessible(field);Object value = ReflectionUtils.getField(field, bean);System.out.println(value);}static class ExampleBean {private Map<String, String> mapAttribute;public void setMapAttribute(Map<String, String> mapAttribute) {this.mapAttribute = mapAttribute;}}
}
总结 / oauth2示例
还有哪些实用内置类呢?欢迎小伙伴们留言,我会研究一下记录在博文里,同时会署名提供的朋友。
最近看到好多朋友在问oauth2的demo,我之前写过一个,不是很详细(大致功能都有)有兴趣的朋友可以参考一下。gitee地址:
相关文章:
spring里面内置的非常实用的工具
一 、请求数据记录 Spring Boot提供了一个内置的日志记录解决方案,通过 AbstractRequestLoggingFilter 可以记录请求的详细信息。 AbstractRequestLoggingFilter 有两个不同的实现类,我们常用的是 CommonsRequestLoggingFilter。 通过 CommonsRequestL…...
计算机毕业设计 基于Python内蒙古旅游景点数据分析系统 Django+Vue 前后端分离 附源码 讲解 文档
🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…...
centos7 docker部署nacos
1. 一行代码安装git yum -y install git 2. 下载最新版nacos源码: git clone https://github.com/nacos-group/nacos-docker.git 进入nacos-docker文件 cd nacos-docker 3.docker安装数据库Mysql8 按这个来就行,非常好 Docker安装mysql8-超详细、每…...
短视频矩阵源码/短视频矩阵系统搭建/源码开发知识分享
集星云推智剪获客系统,通过自主研发的高效发布模式,为企业提供稳定的接口与自动化操作,助力企业实现短视频矩阵的构建。该系统整合了十大核心功能,包括AI辅助文案撰写、视频剪辑、智能去重、内容拆分、文字转语音、文本提取、批量…...
Git使用教程-将idea本地文件配置到gitte上的保姆级别教程
🤹♀️潜意识起点:个人主页 🎙座右铭:得之坦然,失之淡然。 💎擅长领域:前端 是的,我需要您的: 🧡点赞❤️关注💙收藏💛 是我持…...
论文 | Reframing Instructional Prompts to GPTk’s Language
作者:Swaroop Mishra, Daniel Khashabi, Chitta Baral, Yejin Choi, Hannaneh Hajishirzi 论文摘要:语言模型 (LM) 更容易遵循哪些类型的指令提示? 我们通过进行广泛的实证分析来研究这个问题,这些分析阐明了成功指令提示的重要特…...
C++ Qt / VS2019 +opencv + onnxruntime 部署语义分割模型【经验2】
前序工作 C Qt / VS2019 opencv onnxruntime 部署语义分割模型【经验】 引言 前序工作中介绍了Pytorch模型如何转为ONNX格式,以及在Python中如何使用onnx模型 介绍了如何在VA或QT中配置Onnxruntime运行库 本文重点列出全部源代码及其使用 依赖库 onnxruntime…...
代码随想录算法训练营Day9
232.用栈实现队列 Collection——List——Vector类——Stack类 class MyQueue {Stack<Integer> stackIn;Stack<Integer> stackOut;public MyQueue() {stackInnew Stack();stackOutnew Stack();} public void push(int x) {stackIn.push(x);}public int pop() {no…...
2025秋招NLP算法面试真题(二十)-有监督微调基本概念
1.基本概念 1.微调方法是啥?如何微调? 微调(Fine-tuning)是一种迁移学习的方法,用于在一个预训练模型的基础上,通过在特定任务的数据上进行有监督训练,来适应该任务的要求并提高模型性能。微调利用了预训练模型在大规模通用数据上学习到的语言知识和表示能力,将其迁移…...
使用宝塔部署项目在win上
项目部署 注意: 前后端部署项目,需要两个域名(二级域名,就是主域名结尾的域名,需要在主域名下添加就可以了),前端一个,后端一个 思路:访问域名就会浏览器会加载前端的代…...
[大语言模型-论文精读] Diffusion Model技术-通过时间和空间组合扩散模型生成复杂的3D人物动作
Generation of Complex 3D Human Motion by Temporal and Spatial Composition of Diffusion Models L Mandelli, S Berretti - arXiv preprint arXiv:2409.11920, 2024 通过时间和空间组合扩散模型生成复杂的3D人物动作 摘要 本文提出了一种新的方法࿰…...
vue 引入 esri-loader 并加载地图
记录一下: npm i esri-loader 引入css 在app.vue中 <style> import url(https://js.arcgis.com/4.6/esri/css/main.css); </style> 新建js文件 在js文件中引入esri-loader 并加载其init.js文件 加载init.js 需要其中的loadScript 部分如下&…...
LobeChat:使用服务端数据库部署 - Docker+NextAuth(github)+腾讯云
总流程 Docker部署 身份验证服务-NextAuth github S3存储服务 腾讯云COS 1. 安装Docker brew install docker --cask2. 创建pgvector容器(PostgresSQL) docker run --name [myPgvector] -p 5432:5432 -e POSTGRES_PASSWORD[pwd] -d -e POSTGRES_USER[username] pgvector/…...
长列表加载性能优化
一、长列表优化概述 列表是应用开发中最常见的一类开发场景,它可以将杂乱的信息整理成有规律、易于理解和操作的形式,便于用户查找和获取所需要的信息。应用程序中常见的列表场景有新闻列表、购物车列表、各类排行榜等。随着信息数据的累积,特…...
Vue ElemetUI table的行实现按住上下键高亮上下移动效果
1、添加初始化的方法 // 添加键盘事件监听器: mounted() {window.addEventListener(keydown, this.handleKeydown);}, // 这段代码的作用是在 Vue 组件销毁之前移除一个键盘事件监听器 // 这样做可以确保当组件不再使用时,不会留下任何未清理的事件监听…...
windows C++-指定特定的计划程序策略
通过计划程序策略,可控制计划程序在管理任务时使用的策略。 本文演示如何使用计划程序策略来增加将进度指示器打印到控制台的任务的线程优先级。 示例 以下示例并行执行两个任务。 第一个任务计算第 n 个斐波那契数。 第二个任务将进度指示器打印到控制台。 第一…...
python脚本程序怎么写更优雅?argparse模块巧妙应用
前言 命令行程序,也称CLI程序,另一个直观的名字是脚本程序,简称脚本,由于没有图形用户界面(GUI),所以脚本程序常见的交互方式有3种: 1、脚本程序中读取环境变量,比如env…...
【React】(推荐项目)使用 React、Socket.io、Nodejs、Redux-Toolkit、MongoDB 构建聊天应用程序 (2024)
使用 React、Socket.io、Nodejs、Redux-Toolkit、MongoDB 构建聊天应用程序 (2024) 学习使用 React、Socket.io、Node.js、Redux-Toolkit 和 MongoDB 构建响应式实时消息聊天应用程序。这个项目涵盖了从设置到实施的所有内容,提供了宝贵的见解和实用技能。无论您是…...
C++:std::move 和 std::forward
先说结论: std::forward:用于完全按照传递的参数转发,保留其值类别(左值或右值)std::move:用于将对象转换为右值引用,通常用于启用移动语义并转移所有权 示例: 先看一个简单的示例࿰…...
PHP探索校园新生态校园帮小程序系统小程序源码
探索校园新生态 —— 校园帮小程序系统,让生活更精彩! 🌱【开篇:走进未来校园,遇见新生态】🌱 你是否厌倦了传统校园的繁琐与单调?是否渴望在校园里也能享受到便捷、智能的生活体验࿱…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
