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

一、相关往期文章

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

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

二、需求分析

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

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

三、代码实现

controller层正常写就行

//该方法只对使用了@RequestBody注解的参数生效
@RestControllerAdvice
public class GlobalRequestAdvice implements RequestBodyAdvice {
    @Override
    public 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 类型。
     */
    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
        return new HttpInputMessage() {
            @Override
            public 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);}
            @Override
            public HttpHeaders getHeaders() {
                return httpInputMessage.getHeaders();
            }};}

    /**
     * 读取参数后执行
     *
     * @param o
     * @param httpInputMessage
     * @param methodParameter
     * @param type
     * @param aClass
     * @return
     */
    @Override
    public 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
     */
    @Override
    public 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() {
    @Override
    public 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);
    }

    @Override
    public 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 {

    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        // 支持所有请求体的处理
        return true;
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 在读取请求体之后记录日志
        System.out.println("Request Body: " + body);
        return body;
    }

    @Override
    public 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 请求体处理的一种机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/729461.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

360°环绕拍摄图片的作用 欧保图 ORBITVU

360环绕拍摄图片在电商中的应用及其优势 ORBITVU 波兰 欧保图 360环绕拍摄图片是一种动态的产品展示方式&#xff0c;它允许消费者从不同角度全方位地查看产品&#xff0c;这种交互式的体验大大增强了用户的购物体验。以下是360环绕拍摄图片在电商中的一些具体应用及其带来的优…

【Linux必备工具】自动化构建工具makefile的使用详解

目录 引言 Makefile 简介 依赖关系与依赖方法 make运行规则 依赖关系示例 依赖方法 Makefile 工作原理 示例代码 清理项目与伪目标 清理示例 .PHONY总是被执行 文章手稿&#xff1a; 文章手稿见文末~ 引言 项目构建时遇到的各种挑战如文件编译顺序、库链接、依赖…

“湖仓一体架构及其应用”写作框架,系统架构设计师

论文真题 随着5G、大数据、人工智能、物联网等技术的不断成熟&#xff0c;各行各业的业务场景日益复杂&#xff0c;企业数据呈现出大规模、多样性的特点&#xff0c;特别是非结构化数据呈现出爆发式增长趋势。在这一背景下&#xff0c;企业数据管理不再局限于传统的结构化OLTP…

高互动UI设计揭秘:动画效果如何提升用户体验

动画&#xff0c;由于其酷的视觉冲击&#xff0c;往往会产生极好的用户体验。UI设计中的动态效果可以使用户界面看起来更酷&#xff0c;特别是界面的功能动画&#xff0c;是UX设计的重要组成部分&#xff0c;不容忽视。为什么UI设计的动态效果如此重要&#xff1f;接下来&#…

WIFI6E中的MESH组网功能

什么是WIFI6E和MESH组网&#xff1f; WIFI 6E 是扩展到6GHz 频段的WIFI 6无线通信技术&#xff0c;而“WIFI 6E”中的“6”是指WIFI技术的“第6代”&#xff0c;“E”则是指使用新频段的标准的最新扩展。WIFI 6E通过增加6GHz频段&#xff0c;提供更高的带宽、更低的延迟和更大…

探索Lazada商品数据宝库——一键获取商品详细数据信息

一、引言 在电商领域&#xff0c;Lazada凭借其广泛的商品种类和便捷的购物体验&#xff0c;成为东南亚地区备受欢迎的电商平台。然而&#xff0c;对于许多商家和数据分析师来说&#xff0c;获取商品详细数据信息却是一项繁琐而重要的任务。为了解决这个问题&#xff0c;我们精…

深圳学区房断崖式跌价,3年跌去10万元,更可怕的还在后面

就在房市回暖之际&#xff0c;深圳的学区房却传来让人震惊的消息&#xff0c;深圳八卦岭有小区的房价三年时间从14万元每平方跌至4万元每平方&#xff0c;这对于当下的楼市无疑是重磅炸弹&#xff0c;对人们的购房行为将产生重要影响。 深圳这个受到关注的小区为一个宿舍小区&a…

图像分割(二)——低照度下自然场景下图像分割的一种新方法

一天傍晚&#xff0c;在景观河散步&#xff0c;看到景观河旁边雕塑鸭子&#xff0c;就用手机拍摄下来&#xff0c;但由于是晚上光线不是太好&#xff0c;且雕塑下面的地板有条纹和阴影。想着尝试用传统的数字图像处理方法把鸭子从自然场景中提取出来。 读入低照度下图像&#…

Seal^_^【送书活动第7期】——《IT项目经理进阶之道》

Seal^_^【送书活动第7期】——《IT项目经理进阶之道》 一、参与方式二、本期推荐图书2.1 作者荐语2.2 编辑推荐2.3 图书简介2.4 前言2.5 目 录 三、正版购买 从领导、客户、下属、供应商四个角度&#xff0c;介绍IT项目经理在实际工作中需要面对的挑战&#xff0c;以及一些常见…

【网络安全学习】漏洞扫描:-03- Nikito与Wapiti漏洞扫描的使用

1️⃣ Nikto漏洞扫描 Nikto是一个开源的Web扫描评估程序&#xff0c;它可以对目标Web服务器进行快速而全面的检查&#xff0c;以发现各种潜在的安全问题和漏洞。 &#x1f170;️ 如何使用 ❓ nikto -Display 1234ep -h [域名或IP地址] -o nikto.html # -h参数&#xff1a;指…

实战18:基于tkinter+jupyter notebook开发的情感分析系统

项目演示: 完整代码: import pandas as pd import numpy as np from collections import Counter import re import jieba from tqdm import tqdm from sklearn.metrics import roc_curve, auc import joblib import gensim from sklearn.svm import SVC from gensim.mode…

docker启动nacos挂载目录并修改配置文件

1 通过 Docker 拉取 nacos 镜像 docker pull nacos/nacos-server:v2.1.22 创建宿主机挂载目录 # 用于挂载 nacos 的日志 mkdir -p /mydata/nacos_home/logs/ # 用于挂载 nacos 的配置 mkdir -p /mydata/nacos_home/conf/ # 用于挂载 nacos 的数据 mkdir -p /mydata/nacos_hom…

小林图解系统-四.内存管理 4.1 为什么要有虚拟内存?

虚拟内存 单片机没有操作系统&#xff0c;单片机的CPU是直接操作内存的物理地址。 要想在内存中同时运行两个程序是不可能的。如果第一个程序在2000的位置写入一个新的值&#xff0c;将会擦掉第二个程序存放在相同位置上的所有内容&#xff0c;所以同时运行两个程序会立刻崩溃…

远程桌面修改端口号后无法连接,怎么解决

远程桌面连接让用户在不同地点&#xff0c;不同设备上远程控制一台计算机&#xff0c;很大程度上节约了用户的成本并且提高了办公的灵活性和高效性。有时候修改了端口号就会连接不上&#xff0c;那该怎么办呢&#xff1f; 1. 检查本地计算机和远程计算机是否都连接了网络且网…

《精通嵌入式Linux编程》——解锁嵌入式Linux开发的无限可能

文章目录 &#x1f4d1;前言一、书籍概览与作者风采二、内容详解与特色亮点2.1 嵌入式Linux基础与入门2.2 系统编程与内核探索2.3 驱动开发与实战演练2.4 内存管理与性能优化2.5 系统调试与性能提升2.6 综合项目实践与案例分析 三、书籍价值与应用展望 &#x1f4d1;前言 在当今…

利用反向代理编写HTTP抓包工具——可视化界面

手写HTTP抓包工具——可视化界面 项目描述语言golang可视化fynev2功能代理抓包、重发、记录 目录 1. 示例1.1 主界面1.2 开启反向代理1.3 抓包1.4 历史记录1.5 重发 2. 核心代码2.1 GUI2.1 抓包 3. 结语3.1 传送门 1. 示例 1.1 主界面 1.2 开启反向代理 1.3 抓包 1.4 历史记录…

国产32位高精度低功耗DSP音频处理芯片-DU561

DU561是一款集成多种音效算法高性能32位DSP音频处理芯片&#xff1b;具有高速、高精度、高稳定性等特点&#xff0c;能实现对音频信号的滤波、增强、降噪、混响、变调等处理&#xff0c;广泛应用于音频系统、通信系统、汽车音响、家庭影院、舞台设备等领域。 音频处理可以更好地…

ShuffleNet系列论文阅读笔记(ShuffleNetV1和ShuffleNetV2)

目录 ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices摘要Approach—方法Channel Shuffle for Group Convolutions—用于分组卷积的通道重排ShuffleNet Unit—ShuffleNet单元Network Architecture—网络体系结构 总结 ShuffleNet V2: Pra…

工业无线网关在实际生产中的应用效果和价值-天拓四方

随着智能制造的快速发展&#xff0c;工业无线网关作为关键通信设备&#xff0c;在提升生产效率、优化生产流程、实现设备间的互联互通等方面发挥着越来越重要的作用。以下是一个关于工业无线网关在智能制造行业应用的具体案例&#xff0c;展示了其在实际生产中的应用效果和价值…