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

SpringBoot 实现RequestBodyAdvice封装统一接受类功能

一、相关往期文章

SpringBoot+Vue实现AOP系统日志功能_aop的vue完整项目

Spring AOP (面向切面编程)原理与代理模式—实例演示_面向切面aop原理详解

二、需求分析

按照一般情况,统一接受类可以像以下的方式进行处理:

        如果不想使用 @RequestBody RequestPack<RequestPackSave> requestPack  当然也可以使用AOP在controller层数据执行之前,对数据进行处理。

三、代码实现

controller层正常写就行

//该方法只对使用了@RequestBody注解的参数生效
@RestControllerAdvice
public class GlobalRequestAdvice implements RequestBodyAdvice {@Overridepublic boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {// 此处true代表执行当前advice的业务,false代表不执行return true;}/*** 读取参数前执行** @param httpInputMessage* @param methodParameter* @param type* @param aClass* @return 返回一个新的 HttpInputMessage,该消息可能包含修改后的请求体。* @throws IOException* HttpInputMessage httpInputMessage: 表示原始的 HTTP 请求消息。* MethodParameter methodParameter: 表示控制器方法的参数。* Type type: 表示方法参数的类型。* Class<? extends HttpMessageConverter<?>> aClass: 表示将要使用的* HttpMessageConverter 类型。*/@Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {return new HttpInputMessage() {@Overridepublic InputStream getBody() throws IOException {String bodyStr = IOUtils.toString(httpInputMessage.getBody(), "utf-8");GlobalHttpReceive httpReceive = GsonUtil.jsonToObject(bodyStr, GlobalHttpReceive.class);if (httpReceive != null) {Object data = httpReceive.getReqData();if (data != null) {return IOUtils.toInputStream(GsonUtil.objectToJson(data), "utf-8");}}throw new SSError(GlobalCodeEnum.RequestFormatError);}@Overridepublic HttpHeaders getHeaders() {return httpInputMessage.getHeaders();}};}/*** 读取参数后执行** @param o* @param httpInputMessage* @param methodParameter* @param type* @param aClass* @return*/@Overridepublic Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {return o;}/*** 无请求时的处理** @param o* @param httpInputMessage* @param methodParameter* @param type* @param aClass* @return*/@Overridepublic Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {return o;}
}

四、解释说明

  • RequestBodyAdvice 的设计初衷是为了拦截并处理那些使用了 @RequestBody 注解的参数。也就是说,当一个控制器方法参数被 @RequestBody 注解标注时,Spring 会在处理该参数时调用 RequestBodyAdvice
  • supports 方法的参数MethodParameter methodParameter: 代表方法参数的相关信息。Type type: 代表方法参数的类型。Class<? extends HttpMessageConverter<?>> aClass: 代表将要使用的 HttpMessageConverter 类型。
  • 始终返回 true:

    在实现 RequestBodyAdvice 接口的类中,supports 方法返回 true 意味着对于所有进入的请求体参数,都会执行 beforeBodyReadafterBodyRead 和 handleEmptyBody 等方法。换句话说,无论请求体的内容是什么,只要这个参数被 @RequestBody 注解标记,当前的 RequestBodyAdvice 实现就会对其进行处理。
  • 当 Spring 处理某个带有 @RequestBody 注解的方法参数时,会调用 supports 方法。
  • 由于 supports 方法始终返回 true,因此所有带有 @RequestBody 注解的参数都会被当前的 RequestBodyAdvice 处理。
return new HttpInputMessage() {@Overridepublic InputStream getBody() throws IOException {String bodyStr = IOUtils.toString(httpInputMessage.getBody(), "utf-8");GlobalHttpReceive httpReceive = GsonUtil.jsonToObject(bodyStr, GlobalHttpReceive.class);if (httpReceive != null) {Object data = httpReceive.getReqData();if (data != null) {return IOUtils.toInputStream(GsonUtil.objectToJson(data), "utf-8");}}throw new SSError(GlobalCodeEnum.RequestFormatError);}@Overridepublic HttpHeaders getHeaders() {return httpInputMessage.getHeaders();}
};

这段代码是一个全局请求处理的拦截器类,主要实现了Spring的RequestBodyAdvice接口,用于对请求的@RequestBody参数进行处理。具体功能如下:

  1. supports方法用于判断是否执行当前advice的业务逻辑,这里始终返回true,表示对所有使用了@RequestBody注解的参数进行处理。

  2. beforeBodyRead方法在读取参数前执行,首先将请求体内容转换为字符串,然后尝试将其转换为GlobalHttpReceive对象,提取其中的reqData字段。如果reqData不为空,则将其转换为JSON字符串后重新封装成InputStream返回;否则抛出SSError(GlobalCodeEnum.RequestFormatError)异常。

  3. afterBodyRead方法在读取参数后执行,这里直接返回参数对象。

  4. handleEmptyBody方法用于处理无请求体时的情况,这里也直接返回参数对象。

        通过始终返回 truesupports 方法确保了任何带有 @RequestBody 注解的参数都会进入 RequestBodyAdvice 的处理方法中,从而实现对这些参数的统一预处理逻辑。这种设计使得开发者可以集中管理和处理所有请求体的数据,而不需要在每个控制器方法中分别编写重复的处理代码。

五、对比分析

虽然 RequestBodyAdvice 并不是严格的 AOP,但它确实体现了 AOP 的一些思想。举个例子,如果你要记录所有请求体的数据,可以这样实现:

import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter;
import java.lang.reflect.Type;@ControllerAdvice
public class LoggingRequestBodyAdvice extends RequestBodyAdviceAdapter {@Overridepublic boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {// 支持所有请求体的处理return true;}@Overridepublic Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {// 在读取请求体之后记录日志System.out.println("Request Body: " + body);return body;}@Overridepublic Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {// 处理空请求体的情况System.out.println("Request Body is empty");return body;}
}

  RequestBodyAdvice 并不完全属于 AOP 范畴,但它利用了类似于 AOP 的拦截机制来处理请求体的读取过程。在 Spring Boot 中,真正的 AOP 通常通过 @Aspect 注解和切点表达式来实现,用于更广泛的应用场景。而 RequestBodyAdvice 则是专门针对 HTTP 请求体处理的一种机制。

相关文章:

SpringBoot 实现RequestBodyAdvice封装统一接受类功能

一、相关往期文章 SpringBootVue实现AOP系统日志功能_aop的vue完整项目 Spring AOP (面向切面编程&#xff09;原理与代理模式—实例演示_面向切面aop原理详解 二、需求分析 按照一般情况&#xff0c;统一接受类可以像以下的方式进行处理&#xff1a; 如果不想使用 Request…...

贪吃蛇——c语言版

文章目录 演示效果实现的基本功能技术要点源代码实现功能GameStart打印欢迎界面和功能介绍绘制地图创建蛇创建食物 GameRun打印提示信息蛇每走一步 GameEnd蛇死亡后继续游戏 演示效果 贪吃蛇1.0演示视频 将终端应用程序改为控制台主机 实现的基本功能 贪吃蛇地图绘制蛇吃食物的…...

ctr/cvr预估之WideDeep模型

ctr/cvr预估之Wide&Deep模型 在探索点击率&#xff08;CTR&#xff09;和转化率&#xff08;CVR&#xff09;预估的领域中&#xff0c;我们始终追求的是一种既能捕获数据中的线性关系&#xff0c;又能发现复杂模式的模型。因子分解机&#xff08;Factorization Machines, …...

快速生成基于vue-element的后台管理框架,实现短时间二次开发

你是否遇到过当你想要独立开发一个项目时对反复造轮子的烦扰&#xff1f; 这种流水线的操作实在让人受不了 而vue-element-template很好的帮你解决了这个烦恼 只需克隆下来&#xff0c;改改图标&#xff0c;模块名&#xff0c;甚至样式&#xff0c;就会变成一个全新的自己的项目…...

PCIe 7.0 要来了,一文看懂PCIe发展和技术

PCIe&#xff08;Peripheral Component Interconnect Express&#xff09;&#xff0c;即外围组件高速串行扩展总线标准&#xff0c;自其诞生以来&#xff0c;已成为计算机硬件中不可或缺的一部分。它以其高速串行通信能力和不断演进的技术规范&#xff0c;满足了日益增长的数据…...

API-事件类型

学习目标&#xff1a; 掌握事件类型 学习内容&#xff1a; 事件类型鼠标事件焦点事件键盘事件文本事件focus选择器案例 事件类型&#xff1a; 鼠标事件&#xff1a; <title>事件类型-鼠标事件</title><style>div {width: 200px;height: 200px;background-c…...

解决poweroff时需要等待其他服务关闭问题

当我们在执行poweroff或者reboot时会出现某个服务需要等待才能关闭系统,这个时候就可以在服务中添加如下: After=shutdown.target Conflicts=reboot.target halt.target poweroff.target Before=shutdown.target reboot.target halt.target poweroff.target具体实例: [Uni…...

ThinkPHP-导入Excel表格(通用版)

一、版本说明 1.PHP8.2、MySQL8.0、ThinkPHP8.0 2.使用前安装phpspreadsheet composer require phpoffice/phpspreadsheet 二、技术说明 因本人采用前后端分离&#xff0c;因此上传文件以及导入表格为分离开发&#xff0c;如无需分离开发则自行合并开发即可。 1.第一步&a…...

毕昇jdk教程

毕昇jdk教程指南链接&#xff1a;Wiki - Gitee.com...

【R语言】地理探测器模拟及分析(Geographical detector)

地理探测器模拟及分析 1. 写在前面2. R语言实现2.1 数据导入2.2 确定数据离散化的最优方法与最优分类2.3 分异及因子探测器&#xff08;factor detector&#xff09;2.4 生态探测器&#xff08;ecological detector&#xff09;2.5 交互因子探测器&#xff08;interaction dete…...

深入理解Qt属性系统[Q_PROPERTY]

Qt 属性系统是 Qt 框架中一个非常核心和强大的部分&#xff0c;它提供了一种标准化的方法来访问对象的属性。这一系统不仅使得开发者能够以一致的方式处理各种数据类型&#xff0c;还为动态属性的管理提供了支持&#xff0c;并与 Qt 的元对象系统紧密集成。在这篇文章中&#x…...

【C语言课程设计】员工信息管理系统

员工信息管理系统 在日常的企业管理中&#xff0c;员工信息的管理显得尤为重要。为了提高员工信息管理的效率&#xff0c;我们设计并实现了一个简单的员工信息管理系统。该系统主要使用C语言编写&#xff0c;具备输入、显示、查询、更新&#xff08;增加、删除、修改&#xff…...

「动态规划」如何求最长递增子序列的长度?

300. 最长递增子序列https://leetcode.cn/problems/longest-increasing-subsequence/description/ 给你一个整数数组nums&#xff0c;找到其中最长严格递增子序列的长度。子序列是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其…...

深度神经网络DNN概念科普

深度神经网络DNN概念科普 深度神经网络&#xff08;Deep Neural Network, DNN&#xff09;是机器学习领域中一类具有多层结构的神经网络模型&#xff0c;它能够通过学习数据中的复杂模式来解决非线性问题。下面是对深度神经网络的详细解析&#xff1a; 基本组成部分 输入层&…...

Tomcat WEB站点部署

目录 1、使用war包部署web站点 2、自定义默认网站目录 3、部署开源站点&#xff08;jspgou商城&#xff09; 对主机192.168.226.22操作 对主机192.168.226.20操作 上线的代码有两种方式&#xff1a; 第一种方式是直接将程序目录放在webapps目录下面&#xff0c;这种方式…...

IPv6 中 MAC 33:33 的由来

一、33:33 由来 1. RFC9542 - 2024-05-02 Note IANA allocates addresses under the IANA OUI (00-00-5E) as explained in [RFC9542]. Unicast addresses under the IANA OUI start with 00-00-5E, while multicast addresses under the IANA OUI start with 01-00-5E. In t…...

告别手动邮件处理:使用imbox库轻松管理你的收件箱

imbox库简介&#xff1a; imbox是一个强大的Python库,专为与IMAP服务器交互而设计.IMAP&#xff08;Internet Message Access Protocol&#xff09;是一种用于电子邮件的标准协议,允许用户在远程服务器上管理邮件.imbox库通过IMAP协议与邮件服务器通信,帮助用户轻松地读取、搜索…...

Ubuntu 18.04 安装 PCL 1.14.1

在进行科研项目时&#xff0c;我们常常需要将 C 和 Python 结合起来编程。然而&#xff0c;每次将 PCL&#xff08;Point Cloud Library&#xff09;的内容添加到 CMakeLists.txt 文件中时都会报错。在深入分析后&#xff0c;我们推测可能是当前使用的 PCL 1.8 版本与现有程序不…...

公司logo设计大全怎么找?直接帮你设计logo

公司logo设计大全怎么找&#xff1f;在品牌塑造的过程中&#xff0c;Logo无疑是至关重要的一环。一个优秀的Logo不仅能够有效传达公司的核心理念和品牌形象&#xff0c;还能在消费者心中留下深刻的印象。然而&#xff0c;对于许多初创公司或小型企业来说&#xff0c;制作出适合…...

如何调整C#中数组的大小

前言 数组存储多个相同类型的一种非常常用的数据结构。它长度是固定&#xff0c;也就是数组一旦创建大小就固定了。C# 数组不支持动态长度。那在C#中是否有方法可以调整数组大小呢&#xff1f;本文将通过示例介绍一种调整一维数组大小的方法。 方法 数组实例是从 System.Arr…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

PostgreSQL——环境搭建

一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在&#xff0…...