【Spring MVC】获取 @RequsetBody 标识的对象,使用适配器模式增加代码可读性

news2024/10/6 20:32:01

1. 前言

一个技术需求引发的思考和实践:

  • 思考
    • 用 AOP 把校验代码
  • 实践
    • 用 Spring MVC 的 RequestBodyAdvice 做AOP逻辑
    • 继承 RequestBodyAdviceAdapter 实现自己的 适配器
    • 用自己的适配器让代码可读性增加
    • 熟悉 Spring MVC 、Java 反射的一些实践
  • 本文内容
    • 澄清一个AOP校验JSON内容的思路
    • 复习适配器模式

在这里插入图片描述
在这里插入图片描述

2. 怎么选择切面?

  • 一个大致的切面
    在这里插入图片描述
  • 从 Spring 4.2 开始,有新的切面出现,可以切到 RequestBody 上,这个切面更符合技术需求的粒度。
	public interface RequestBodyAdvice 

3. RequestBody 的切面的描述

  • RequestBodyAdvice
public interface RequestBodyAdvice {
	// 什么时候切
	boolean supports(MethodParameter methodParameter, Type targetType,
			Class<? extends HttpMessageConverter<?>> converterType);

	// 切到读body前的位置
	HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
			Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException;

	// 切到读body后的位置
	Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
			Type targetType, Class<? extends HttpMessageConverter<?>> converterType);
	
	// 处理空body
	@Nullable
	Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter,
			Type targetType, Class<? extends HttpMessageConverter<?>> converterType);
}

根据接口描述,直接实现这个接口需要读很多参数的含义,其实实现业务需求仅需要:

  • 实现少部分方法
  • 了解少部分方法的参数

4. Spring 提供的 RequestBody 的适配器

  • RequestBodyAdviceAdapter

    该适配器简化了一个方法,并提供了必要的三个方法的实现

public abstract class RequestBodyAdviceAdapter implements RequestBodyAdvice {

	@Override
	public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
			Type targetType, Class<? extends HttpMessageConverter<?>> converterType)
			throws IOException {
		return inputMessage;
	}

	@Override
	public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
			Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
		return body;
	}

	@Override
	@Nullable
	public Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage,
			MethodParameter parameter, Type targetType,
			Class<? extends HttpMessageConverter<?>> converterType) {
		return body;
	}

}

根据适配器描述 afterBodyRead 方法能获取到 body 参数,我们能找到重点

  • afterBodyRead 方法
  • afterBodyRead 方法的 body 参数
    我们可以根据这个特点,实现自己的适配器

5. 拓展 Spring 的适配器,实现自己的适配器

public abstract class AdviceAdapter extends RequestBodyAdviceAdapter {

	// 暴露关心的参数
	abstract void validate(Object body);

	@Override
	public boolean supports(MethodParameter methodParameter, @Nullable Type targetType, @Nullable Class<? extends HttpMessageConverter<?>> converterType) {
		return Objects.nonNull(methodParameter.getMethodAnnotation(RequestValidated.class));
	}

	@Override
	@Nonnull
	public Object afterBodyRead(@Nonnull Object body, @Nullable HttpInputMessage inputMessage, MethodParameter parameter,
								@Nullable Type targetType, @Nullable Class<? extends HttpMessageConverter<?>> converterType) {
		// 嵌入切面
		validate(body);
		return input;
	}
}

6. 在自己的适配器上实现逻辑

// 注意切 RequestBody 用的注解是 ControllerAdvice
@ControllerAdvice
public class ValidateAdvice extends AdviceAdapter {

	// 具体实现
    @Override
    void validate(Object json) {
        
    }
}

7. 后记

之前整理过适配器模式的内容,现在感受更深了。
适配器可以多个配合起来工作,一个形象的图用来比喻这种设计:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mysql 调优

前言 硬件层面&#xff1a;使用固态硬盘、扩大内存、加大带宽等等 架构层面&#xff1a;主从复制实现读写分离【一主一 或 双主双从】 表结构层面&#xff1a;对表结构进行垂直拆分、水平分表、分库分表。常用的数据库中间件有&#xff1a;MySQL Proxy、MyCat以及ShardingSphe…

电脑C盘的清理 | 微信QQ缓存信息

记录一下我处理C盘爆满时的几个方法&#xff0c;基本上都是可以日常使用的。 一、磁盘清理 链接 二、查看具体哪些文件占内存 win图标右击 -----> 点击“系统&#xff08;Y&#xff09;” 点击查看具体是哪些文件夹哪些app占用了大量的内存&#xff0c;并选择删除部分…

第二章 re模块

1. re模块介绍 正则表达式 在处理字符串时&#xff0c;经常会有查找符合某些复杂规则的字符串的需求。正则表达式就是用于描述这些规则的工具。换句话说&#xff0c;正则表达式就是记录文本规则的代码。 re 模块 Python 提供了 re 模块用于实现正则表达式的操作。在实现时&…

CTFshow-pwn入门-前置基础pwn23-pwn25

pwn23-25的题目会涉及到ret2shellcode、ret2libc等内容&#xff0c;本篇文章只会侧重研究这几道题目的wp&#xff0c;不会过多涉及到ret2shellcode、ret2libc的基本原理&#xff0c;等有时间再来写关于ret2libc、ret2shellcode…的相关内容。大家可以参考CTFwiki的文章去慢慢学…

FPGA_数码管显示UART串口接收的数据

实验目标&#xff1a;通过电脑调试助手向FPGA的UART串口接收模块发送数据&#xff0c;然后数据可以稳定显示在数码管上。 实验目的: 练习UART串口模块和数码管的使用。之前已经有文章详细讲解了串口和数码管的开发&#xff0c;故这里直接提供设计思路供大家参考。 &#xff08…

求解矩阵行列式因子、不变因子、初等因子、Jordan标准形

首先&#xff0c;我们先来简要了解一下行列式因子、不变因子和初等因子的概念。 下面举例说明。 例1 首先&#xff0c;我们要求 λ I − A λI-A λI−A 然后&#xff0c;我们先求行列式因子。 D 2 ( λ ) D_2(λ) D2​(λ)的求法如下&#xff1a; 然后&#xff0c;我们再求…

015、数据库管理之用户和权限

用户和权限 认证与赋权连接过程本地连接远程连接查看用户信息创建用户账号创建角色管理用户账户管理角色设置账号密码忘记root密码实验1-用户和角色实验2-授权注意事项 认证与赋权 认证&#xff1a;对用户进行验证 是权限控制的第一步当用户第一次连接数据库时必须进行认证如果…

【Git】TortoiseGit(小乌龟)配置SSH和使用

目录 1、TortoiseGit&#xff08;小乌龟&#xff09;配置SSH 1.1、右击打开Git命令窗口 1.2、设置Git的全局name和email 1.3、查看是全局名字和邮箱是否设置成功 1.4、生成 sshkey秘钥 2、TortoiseGit&#xff08;小乌龟&#xff09;的使用 2.1、创建本地仓库 2.2、添加…

企业会计软件必备!深入了解为何选择会计软件以及其带来的好处

随着科技的发展&#xff0c;企业需要更加智能化和数字化的财务管理方式&#xff0c;因此会计软件是现代社会的必然产物&#xff0c;会计软件可以帮助企业更有效地进行财务管理。 企业为什么需要会计软件&#xff1f; 提高准确度 通过传统的手工操作财务记录&#xff0c;会有很…

Qt6.2教程——2.介绍 Qt 中的 QWidgets、QMainWindow 和 QDialog

详细介绍 Qt 中的 QWidgets、QMainWindow 和 QDialog Qt 是一个广受欢迎的跨平台 C GUI 库。在 Qt 中&#xff0c;创建图形用户界面的基本单元是 Widget。本文将详细介绍三个重要的 Widget 类&#xff1a;QWidget, QMainWindow 和 QDialog&#xff0c;并比较它们的特点和用途。…

设计模式之原型模式笔记

设计模式之原型模式笔记 说明Prototype(原型)目录UML原型模式示例类图RealizeType类(浅克隆)测试类 原型模式案例奖状类测试类 扩展(深克隆)学生类奖状类测试类 说明 记录下学习设计模式-原型模式的写法。 Prototype(原型) 意图:用原型实例指定创建对象的种类&#xff0c;并…

Spring之IOC容器从入门都手写源码

文章目录 一、IOC容器1、控制反转&#xff08;ioc&#xff09;2、依赖注入3、IoC容器在Spring的实现 二、基于XML管理Bean1、获取bean方式一、根据id获取方式二、根据类型获取方式三、根据id和类型获取bean 2、依赖注入之setter注入3、依赖注入之构造器注入4、特殊值处理5、为对…

基于llama模型进行增量预训练

目录 1、llama模型转换(pytorch格式转换为HuggingFace格式) 1.1、拉取Chinese-LLaMA-Alpaca项目 1.2、准备文件夹 1.3、下载llama官方原始模型 1.4、移动文件到指定位置 1.5、执行转换脚本 2、合并模型 2.1、下载Chinese-LLaMA-Plus-7B模型 2.2、下载chinese_alpaca_p…

【Leetcode60天带刷】day16二叉树—— 104.二叉树的最大深度 , 111.二叉树的最小深度,222.完全二叉树的节点个数

题目&#xff1a; 104. 二叉树的最大深度 给定一个二叉树&#xff0c;找出其最大深度。 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 说明: 叶子节点是指没有子节点的节点。 示例&#xff1a; 给定二叉树 [3,9,20,null,null,15,7]&#xff0c; 3/ \9 20/ …

数字电路基础---寄存器

目录 数字电路基础---寄存器 1、寄存器简介 1.1、寄存器是如何工作的 2、实验任务 3、程序设计 3.1、模块设计 3.2、绘制波形图 4、编写代码 5、仿真验证 5.1、编写 TB 文件 5.2、仿真验证 6、总结 7、拓展训练 数字电路基础---寄存器 寄存器是构成时序逻辑最重要…

理解安卓的视图体系结构

原文链接 理解安卓的视图体系结构 当我们想要写一个页面的时候&#xff0c;通过一个Activity&#xff0c;然后调用其setContentView方法&#xff0c;把一个布局文件当作一个参数传递过去&#xff0c;然后一个页面就好了&#xff0c;但是除此之外&#xff0c;我们还需要与一些组…

【MySql】MySql索引的作用索引的理解

【MySql】MySql索引的作用&&索引的理解 文章目录 索引的作用认识磁盘MySql 与磁盘交互基本单位Page共识索引的理解主键有序问题理解单个Page理解多个Page页目录单页情况多页情况 索引的作用 索引是与效率挂钩的&#xff0c;所以没有索引&#xff0c;可能会存在问题 索…

从0到1搭建属于自己的Gitlab CI/CD平台

文章目录 持续集成(CI)持续交付(CD)Gitlab CI/CD功能和架构本地搭建GitLab CI/CD平台 MCNU云原生&#xff0c;文章首发地&#xff0c;欢迎微信搜索关注&#xff0c;更多干货&#xff0c;第一时间掌握&#xff01; CI和CD是软件开发中常用的缩写&#xff0c;分别代表持续集成&am…

【Unity】 HTFramework框架(四十五)【进阶篇】指令系统-自定义指令

更新日期&#xff1a;2023年6月19日。 Github源码&#xff1a;[点我获取源码] Gitee源码&#xff1a;[点我获取源码] 索引 指令系统1.使用指令系统2.自定义指令1.新建类 MyInstruction2.标记 CustomInstruction 特性3.编写指令的逻辑4.执行自定义指令5.自定义指令的参数6.结尾 …

C进阶 - 数组和指针

Declare an array manually VS malloc or calloc an array 用英文是因为有些东西得用他们的语言才能表达不失真 栈和堆 In C, a heap is a region of memory that is dynamically allocated during runtime. It is used to store variables and data structures that have a …