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探索校园新生态校园帮小程序系统小程序源码
探索校园新生态 —— 校园帮小程序系统,让生活更精彩! 🌱【开篇:走进未来校园,遇见新生态】🌱 你是否厌倦了传统校园的繁琐与单调?是否渴望在校园里也能享受到便捷、智能的生活体验࿱…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...
【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...
