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

使用AOP在切面逻辑中无法获取到requesetBody

使用场景:在接口处理之前,我们需要拿到请求参数,对参数进行校验。注意,这里需要拿到的是原始的请求信息!

一般的获取方式

ServletInputStream inputStream = request.getInputStream();
StringBuilder stringBuilder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, request.getCharacterEncoding()))) {String line;while ((line = reader.readLine()) != null) {stringBuilder.append(line);}
} catch (IOException e) {e.printStackTrace();
}
String requestBody = stringBuilder.toString();

获取requestBody的代码大同小异,可自行搜索。代码没有问题,但是无法获取到requestBody,就要考虑接口方法是否使用了@RequestBody。

在Spring MVC框架中,当你使用@RequestBody注解时,Spring会在将请求转发到控制器方法之前,从HTTP请求体中读取数据并将其反序列化为Java对象。这一处理过程是由HttpMessageConverter完成的,它负责将请求体中的JSON、XML或其他格式的数据转换为Java对象。

请求体只能被读取一次:HTTP请求体是一个输入流,它只能被读取一次。一旦HttpMessageConverter读取了请求体,输入流就被“消耗”掉了,无法再次被读取。因此,当切面尝试访问请求体时,它发现输入流已经为空或不可用。

解决方法:

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;public class CachedBodyHttpServletRequestWrapper extends HttpServletRequestWrapper {private final byte[] cachedBody;public CachedBodyHttpServletRequestWrapper(HttpServletRequest request) throws IOException {super(request);ByteArrayOutputStream outputStream = new ByteArrayOutputStream();InputStream inputStream = request.getInputStream();byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}cachedBody = outputStream.toByteArray();}@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(cachedBody);return new ServletInputStream() {@Overridepublic boolean isFinished() {return byteArrayInputStream.available() == 0;}@Overridepublic boolean isReady() {return true;}@Overridepublic void setReadListener(ReadListener readListener) {}@Overridepublic int read() throws IOException {return byteArrayInputStream.read();}};}public String getCachedBody() {return new String(cachedBody, StandardCharsets.UTF_8);}
}
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;public class CachedBodyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {if (request instanceof HttpServletRequest) {HttpServletRequest httpRequest = (HttpServletRequest) request;CachedBodyHttpServletRequestWrapper cachedBodyRequestWrapper = new CachedBodyHttpServletRequestWrapper(httpRequest);chain.doFilter(cachedBodyRequestWrapper, response);} else {chain.doFilter(request, response);}}@Overridepublic void destroy() {}
}
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<CachedBodyFilter> loggingFilter(){FilterRegistrationBean<CachedBodyFilter> registrationBean = new FilterRegistrationBean<>();registrationBean.setFilter(new CachedBodyFilter());registrationBean.addUrlPatterns("/*");return registrationBean;    }
}

然后在切面里利用CachedBodyHttpServletRequestWrapper 去获取requestBody就可以了。

相关文章:

使用AOP在切面逻辑中无法获取到requesetBody

使用场景&#xff1a;在接口处理之前&#xff0c;我们需要拿到请求参数&#xff0c;对参数进行校验。注意&#xff0c;这里需要拿到的是原始的请求信息&#xff01; 一般的获取方式 ServletInputStream inputStream request.getInputStream(); StringBuilder stringBuilder …...

生成模型:变分自编码器-VAE

1.基本概念 1.1 概率 这里有&#xff1a; x为真实图像&#xff0c;开源为数据集, 编码器将其编码为分布参数 x ^ \hat{x} x^为生成图像, 通过解码器获得 p ( x ) ^ \hat{p(x)} p(x)^​: 观测数据的分布, 即数据集所构成的经验分布 p r e a l ( x ) p_{real}(x) preal​(x): …...

Hive sql执行文件合并配置参数

HIVE自动合并输出的小文件的主要优化手段为&#xff1a;HIVE将会启动一个独立的map-reduce任务进行输出文件的merge。 set hive.merge.mapfiles true&#xff1a; 在只有map的作业结束时合并小文件&#xff0c; set hive.merge.mapredfiles true&#xff1a; 在Map-Reduce的任…...

鸿蒙 ArkUI实现地图找房效果

常用的地图找房功能&#xff0c;是在地图上添加区域、商圈、房源等一些自定义 marker&#xff0c;然后配上自己应用的一些筛选逻辑构成&#xff0c;在这里使用鸿蒙 ArkUI 简单实现下怎么添加区域/商圈、房源等 Marker. 1、开启地图服务 在华为开发者官网&#xff0c;注册应用&…...

一套极简易的直流无刷电机(Deng FOC)开发套件介绍

目录 概述 1. 硬件组成介绍 1.1 主要硬件 1.2 电机驱动板介绍 1.3 2208电机模块 1.3.1 参数介绍 1.3.2 认识2208电机 2 驱动板接口介绍 2.1 PCB接口&#xff08;MCU&#xff09;定义 2.2 功能描述 2.2.1 电机驱动接口 2.2.2 编码器接口 2.2.3 电流输入引脚接口 2.…...

Inception模型详解及代码分析

模型背景 Inception系列模型由Google团队提出,旨在解决CNN分类模型面临的两大挑战: 如何在增加网络深度的同时提升分类性能 如何在保证分类准确率的同时降低计算和内存开销 Inception V1通过引入 并行卷积结构 和 1x1卷积 ,巧妙地解决了这两个问题,在保证模型质量的前提下…...

Springboot AOP 每个接口运行前 修改入参

控制台log输出为何频频失踪?   wxss代码为何频频失效?   wxml布局为何乱作一团?   究竟是道德的沦丧?还是人性的缺失?   让我们一起来 走 跑进科学 前言 麻蛋被这个功能恶心好久 终于解决了 特此记录一下 正文 Before("authCut()")public void cutProc…...

课题推荐——基于GPS的无人机自主着陆系统设计

关于“基于GPS的无人机自主着陆系统设计”的详细展开&#xff0c;包括项目背景、具体内容、实施步骤和创新点。如需帮助&#xff0c;或有导航、定位滤波相关的代码定制需求&#xff0c;请点击文末卡片联系作者 文章目录 项目背景具体内容实施步骤相关例程MATLAB例程python例程 …...

【深度学习】在深度学习训练过程中,数据量太少会导致模型过拟合还是欠拟合?

过拟合与欠拟合 过拟合 : 是指在训练集上表现非常好&#xff0c;但是在新的数据集上表现较差的现象。具体来说&#xff0c;模型在训练集上过度学习&#xff0c;捕捉了数据中的噪声和偶然性&#xff0c;导致它对训练数据的拟合非常精确&#xff0c;但缺乏泛化能力&#xff0c;无…...

js迭代器模式

以前JS原生的集合类型数据结构&#xff0c;只有Array&#xff08;数组&#xff09;和Object&#xff08;对象&#xff09;&#xff1b; 而ES6中&#xff0c;又新增了Map和Set。四种数据结构各自有着自己特别的内部实现&#xff0c;但我们仍期待以同样的一套规则去遍历它们&…...

测试开发基础知识2

10.什么是等价类和边界值法&#xff1f; 1)等价类划分 等价类划分是将系统的输入域划分为若干部分&#xff0c;然后从每个部分选取少量代表性数据进行测试。等价类划分认为如果一个测试用例在某个等价类中的一个值上通过测试&#xff0c;那么它在这个类中的其他值上也…...

PromQL基础使用和案例解析

文章目录 PromQL简介数据类型1、瞬时数据 (Instant vector)2、区间数据 (Range vector)➢ Time Durations➢ Offest modifier➢ modifier 3、标量数据 (Scalar)4、字符串 (String) 条件匹配1、完全匹配2、正则匹配 运算符1、比较运算符2、算数运算符3、逻辑运算符4、聚合运算符…...

使用Python实现基于机器学习的垃圾邮件过滤

友们好! 我的新专栏《Python进阶》正式启动啦!这是一个专为那些渴望提升Python技能的朋友们量身打造的专栏,无论你是已经有一定基础的开发者,还是希望深入挖掘Python潜力的爱好者,这里都将是你不可错过的宝藏。 在这个专栏中,你将会找到: ● 深入解析:每一篇文章都将深…...

MySql根据经纬度查询距离

一、搭建测试 创建数据表() CREATE TABLE sys_test (id int(11) NOT NULL AUTO_INCREMENT COMMENT 主键ID,name varchar(20) DEFAULT NULL COMMENT 名称,longitude decimal(10,6) DEFAULT NULL COMMENT 经度,latitude decimal(10,6) DEFAULT NULL COMMENT 维度,PRIMARY KEY (id…...

Aviatrix Controller 未授权命令注入漏洞复现(CVE-2024-50603)

0x01 产品简介 Aviatrix Controller是一款强大的云网络管理平台,提供简化的跨云网络管理、自动化配置、安全策略、流量监控等功能,帮助企业实现更加灵活、安全和高效的云网络架构,特别适用于多云和混合云环境。主要用于编排和管理各种网络和连接解决方案。它为用户提供了一…...

数据结构与算法之二叉树: LeetCode 109. 有序链表转换二叉搜索树 (Ts版)

有序链表转换二叉搜索树 https://leetcode.cn/problems/convert-sorted-list-to-binary-search-tree/description/ 描述 给定一个单链表的头节点 head &#xff0c;其中的元素 按升序排序 &#xff0c;将其转换为 平衡 二叉搜索树 示例 1 输入: head [-10,-3,0,5,9] 输出:…...

Android NDK开发入门2之适应idm环境

环境搭建 Android NDK开发实战之环境搭建篇(so库,Gemini ai)-CSDN博客 初始配置 前面已经运行了一个简单的初始程序&#xff0c;现在我们来往初始程序添加类和函数&#xff0c;并成功运行的实验。 一级配置 第一层配置主要是cmake文件环境和一些编译选项。 build配置 可参…...

如何隐藏 Nginx 版本号 并自定义服务器信息,提升安全性

&#x1f3e1;作者主页&#xff1a;点击&#xff01; Nginx-从零开始的服务器之旅专栏&#xff1a;点击&#xff01; &#x1f427;Linux高级管理防护和群集专栏&#xff1a;点击&#xff01;点击&#xff01;点击&#xff01; ⏰️创作时间&#xff1a;2025年1月8日8点14分…...

鸿蒙的APP真机调试以及发布

目录&#xff1a; 1、创建好鸿蒙项目2、创建AGC项目3、实现自动签名3.1、手动方式创建签名文件和密码 4、运行项目5、无线真机调试 1、创建好鸿蒙项目 2、创建AGC项目 &#xff08;1&#xff09;在File->Project Structure->Project->Signing Configs中进行登录。(未…...

图像处理|膨胀操作

在图像处理领域&#xff0c;形态学操作是一种基于图像形状的操作&#xff0c;用于分析和处理图像中对象的几何结构。**膨胀操作&#xff08;Dilation&#xff09;**是形态学操作的一种&#xff0c;它能够扩展图像中白色区域&#xff08;前景&#xff09;或减少黑色区域&#xf…...

PCB 相关知识

一.PCB线宽单位换算&#xff1a;100mil 2.54mm 。二.在1盎司的铜厚上过1A电流需要&#xff0c;1mm&#xff08;40mil&#xff09;的线宽。三&#xff1a;不要并排打孔&#xff0c;需要错位打孔&#xff1a;防止回流平面被割裂&#xff0c;绕线辐射。且增加走线空间。四.1:mark…...

Wireshark安装教程(附安装包)

Wireshark 是一款非常流行的、免费开源的网络抓包分析软件&#xff0c;它能捕捉并“翻译”你电脑网络上流过的所有数据包。当网络卡顿、连不上网或者怀疑被黑客攻击时&#xff0c;用它一照&#xff0c;就能看清数据的具体内容、来源和去向&#xff0c;是排查网络故障和网络分析…...

基于File-Based App开发MVP项目仿

Issue 概述 先来看看提交这个 Issue 的作者是为什么想到这个点子的&#xff0c;以及他初步的核心设计概念。?? 本 PR 实现了 Apache Gravitino 与 SeaTunnel 的集成&#xff0c;将其作为非关系型连接器的外部元数据服务。通过 Gravitino 的 REST API 自动获取表结构和元数据&…...

沃虎电子:音频变压器在信号隔离与音频接口中的选型与应用解析

音频变压器作为一种传统的磁性元件&#xff0c;在现代电子设计中依然扮演着不可替代的角色。无论是在广播级音频设备、高端音响、电话接口&#xff0c;还是在工业现场的信号隔离中&#xff0c;音频变压器都能提供出色的共模抑制、地环路隔离和阻抗匹配功能。本文从工程实践出发…...

嵌入式LED亮度校准:轻量级Gamma查表引擎GAMMA库

1. GAMMA库概述&#xff1a;面向嵌入式LED亮度校准的轻量级Gamma查表引擎在嵌入式LED驱动系统中&#xff0c;一个长期被忽视却至关重要的工程问题浮出水面&#xff1a;人眼感知亮度与PWM占空比之间存在显著非线性关系。当MCU向LED输出50% PWM信号时&#xff0c;人眼实际感知的亮…...

深入解析rust-memory-container-cs:Rust内存容器分类与选择指南

深入解析rust-memory-container-cs&#xff1a;Rust内存容器分类与选择指南 【免费下载链接】rust-memory-container-cs Rust Memory Container Cheat-sheet 项目地址: https://gitcode.com/gh_mirrors/ru/rust-memory-container-cs rust-memory-container-cs是一份全面…...

分布式与微服务技术架构

对比项分布式微服务微服务前端框架Vue 2Vue 3React18脚本语言JavaScriptTypeScriptJSX / ES6 / TypeScript构建工具Vue CLIViteViteUI 组件库Element UIElement PlusAnt Design状态管理VuexPiniaRedux Toolkit&#xff08;RTK&#xff09;路由管理Vue Router 3Vue Router 4Reac…...

AI+3D视觉重塑金属圆棒自动化上下料:高精度、快节拍、降成本实战案例

在汽车、金属加工等核心制造领域&#xff0c;金属圆棒作为基础关键工件&#xff0c;其上下料环节的自动化水平直接决定产线效率与产品一致性。传统人工上下料存在强度大、效率低、精度波动、易损伤工件等痛点&#xff0c;而**AI3D视觉引导机器人**正成为破解该场景瓶颈的主流技…...

G-Helper:华硕笔记本轻量化控制解决方案详解

G-Helper&#xff1a;华硕笔记本轻量化控制解决方案详解 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Strix, Scar, and o…...

OpenClaw环境隔离方案:千问3.5-9B在Docker中安全运行

OpenClaw环境隔离方案&#xff1a;千问3.5-9B在Docker中安全运行 1. 为什么需要Docker隔离&#xff1f; 去年我在尝试用OpenClaw自动化处理个人文档时&#xff0c;遇到了一个棘手问题&#xff1a;当AI助手在后台执行文件整理任务时&#xff0c;主机上的Python开发环境突然崩溃…...