【SpringBoot】公共字段自动填充

问题引入

JavaEE开发的时候,新增字段,修改字段大都会涉及到创建时间(createTime),更改时间(updateTime),创建人(craeteUser),更改人(updateUser),如果每次都要自己去setter(),会比较麻烦,可以使用Spring的AOP,对于任意Insert,Update操作进行增强

解决步骤

主要依赖

如果使用了springboot,那就只需要导入这一个,这个框架对spring自带的aop框架进行了优化封装,更好用

事实上,还需要两个依赖,spring-context和spring-aop,不过springboot自带的有

<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version>
</dependency>

注释代码

给那些新增、修改功能中的设置时间、修改人的代码部分注释掉

自定义注解&使用

封装数据库操作类型

/*** 数据库操作类型*/
public enum OperationType {/*** 更新操作*/UPDATE,/*** 插入操作*/INSERT}

自定义注解 

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {// 数据库操作类型:UPDATE INSERTOperationType value();
}

给需要自动填充的方法加上注解 

    /*** 新增员工* @param employee*/@Insert("INSERT INTO employee" +"(name, username, password, phone, sex, id_number, create_time, update_time, create_user, update_user)" +"VALUES" +"(#{name}, #{username}, #{password}, #{phone}, #{sex}, #{idNumber}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser})")@AutoFill(value = OperationType.INSERT)void insert(Employee employee);/*** 修改员工信息* @param employee*/@AutoFill(value = OperationType.UPDATE)void update(Employee employee);/*** 根据ID查询员工* @param id* @return*/@Select("SELECT * FROM employee WHERE id = #{id}")Employee getById(Long id);/*** 密码修改* @param passwordEditDTO*/@AutoFill(value = OperationType.UPDATE)@Update("UPDATE employee SET `password` = #{newPassword} WHERE `id` = #{empId} AND `password` = #{oldPassword}")void updatePwd(PasswordEditDTO passwordEditDTO);

通知类

@Slf4j
@Component
@Aspect
public class AutoFillAspect {/*** 切面 && 指定切入点*/@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")public void autoFillPointCut(){}/*** 切面 && 此方法(autoFill()) 在切入点之前执行* @param joinPoint*/@Before("autoFillPointCut()")public void autoFill(JoinPoint joinPoint) {log.info("开始进行公共字段自动填充...");// 拿到当前被拦截的方法上的数据库操作类型MethodSignature signature = (MethodSignature)joinPoint.getSignature();// 拿到实现类的签名信息,不过我们只需要方法的签名信息,强转成MethodSignatureAutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);// 获得签名对象的注解对象OperationType operationType = autoFill.value(); // 拿到数据库操作类型// 拿到当前被拦截方法的方法参数(新增、更改方法的参数一般都是实体类)Object[] args = joinPoint.getArgs();if (args == null || args.length == 0){ // 防止null,防止空参return;}Object entity = args[0]; // 这一行就要求,以后的新增、更改方法参数,实体类必须写在首形参位置// 需填充的数据LocalDateTime now = LocalDateTime.now();Long currentId = BaseContext.getCurrentId();// 根据当前不同的操作类型,使用反射为对应的属性赋值if (operationType == OperationType.INSERT) {// 为4个公共字段赋值try {Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);// 通过反射给对象属性赋值setCreateTime.invoke(entity, now);setUpdateTime.invoke(entity, now);setCreateUser.invoke(entity, currentId);setUpdateUser.invoke(entity, currentId);} catch (Exception e) {e.printStackTrace();}} else if (operationType == OperationType.UPDATE) {// 为2个公共字段赋值try {Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);// 通过反射给对象属性赋值setUpdateTime.invoke(entity, now);setUpdateUser.invoke(entity, currentId);} catch (Exception e) {e.printStackTrace();}}}
}

依赖相关类

公共字段自动填充相关常量

/*** 公共字段自动填充相关常量*/
public class AutoFillConstant {/*** 实体类中的方法名称*/public static final String SET_CREATE_TIME = "setCreateTime";public static final String SET_UPDATE_TIME = "setUpdateTime";public static final String SET_CREATE_USER = "setCreateUser";public static final String SET_UPDATE_USER = "setUpdateUser";
}

线程空间上下文

public class BaseContext {public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();public static void setCurrentId(Long id) {threadLocal.set(id);}public static Long getCurrentId() {return threadLocal.get();}public static void removeCurrentId() {threadLocal.remove();}}

启动类加上注解@EnableAspectJAutoProxy

@SpringBootApplication
@EnableTransactionManagement //开启注解方式的事务管理
@EnableAspectJAutoProxy // 开启注解方式的AOP
@Slf4j
public class SkyApplication {public static void main(String[] args) {SpringApplication.run(SkyApplication.class, args);log.info("server started");}
}

在这段代码中,joinPoint 是 Spring AOP 中的一个概念,表示连接点,即在程序执行过程中切入的某个点。Signature 则是 Signature 接口的实现类之一,用于表示连接点的签名信息,包括方法名、参数列表等。

具体来说,这段代码的含义是从 joinPoint 中获取连接点的签名信息,并将其强制转换为 MethodSignature 类型。然后可以通过 signature 对象获取连接点(被代理方法)的详细信息,比如方法名、参数类型等。

例如,可以通过 signature.getMethod().getName() 获取连接点方法的名称,通过 signature.getParameterTypes() 获取连接点方法的参数类型数组等。

需要注意的是,在实际应用中,我们使用这段代码时需要确保 joinPoint 真正代表了一个方法连接点,否则在强制转换为 MethodSignature 时可能会抛出类型转换异常。

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

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

相关文章

【项目开发】为什么文件名要小写?

未经许可,不得转载。 文章目录 一、可移植性二、易读性三、易用性四、便捷性一、可移植性 Linux 系统对文件名大小写敏感,而 Windows 和 Mac 系统则不敏感。这种差异可能导致跨平台的问题。 例如,以下四个文件名: computerComPutercomPuterCOMPOTer在 Linux 系统上,它们…

ssm127基于SSM的乡镇篮球队管理系统+jsp(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;乡镇篮球队管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本乡镇篮球队管理…

C#获取视频第一帧_腾讯云媒体处理获取视频第一帧

一、 使用步骤&#xff1a; 第一步、腾讯云开启万象 第二步、安装Tencent.QCloud.Cos.Sdk 包 第三步、修改 腾讯云配置 图片存储目录配置 第四步、执行获取图片并保存 二、封装代码 using System.Text; using System.Threading.Tasks;using COSXML.Model.CI; using COSXML.A…

【数据分享】2003-2022年各省土地利用面积统计数据

数据介绍 2003-2022年各省土地利用面积统计数据数据时间2003-2008、2013、2015-2017、2019、2022数据类型excel数据指标土地调查面积/万公顷农用地面积/万公顷园林面积/万公顷牧草地面积/万公顷建设用地面积/万公顷居民点及工矿用地/万公顷交通用地/万公顷水利设施用地/万公顷…

任务调度工具Spring Test

Spring Task 是Spring框架提供的任务调度工具&#xff0c;可以按照约定的时间自动执行某个代码逻辑。 作用&#xff1a;定时自动执行某段Java代码 应用场景&#xff1a; 信用卡每月还款提醒 银行贷款每月还款提醒 火车票售票系统处理未支付订单 入职纪念日为用户发送通知 一.…

20 轮转数组

20 轮转数组 20.1 轮转数组解决方案 class Solution { public:void rotate(vector<int>& nums, int k) {int n nums.size();k k % n; // 如果 k 大于数组长度&#xff0c;取模减少不必要的旋转// 第一步&#xff1a;反转整个数组reverse(nums.begin(), nums.end(…

字符串相关题解

目录 字母异位词 最长公共前缀 博主主页&#xff1a;东洛的克莱斯韦克-CSDN博客 字母异位词 49. 字母异位词分组 - 力扣&#xff08;LeetCode&#xff09; 这道题更像一道语法题&#xff0c;考察对容器的掌握情况。如果按题目要求去模拟&#xff0c;不仅要分析每个字符串&am…

【微软:多模态基础模型】(3)视觉生成

欢迎关注【youcans的AGI学习笔记】原创作品 【微软&#xff1a;多模态基础模型】&#xff08;1&#xff09;从专家到通用助手 【微软&#xff1a;多模态基础模型】&#xff08;2&#xff09;视觉理解 【微软&#xff1a;多模态基础模型】&#xff08;3&#xff09;视觉生成 【微…

CentOS8 启动错误,enter emergency mode ,开机直接进入紧急救援模式,报错 Failed to mount /home 解决方法

先看现场问题截图&#xff1a; 1.根据提示 按 ctrld 输入 root 密码&#xff0c;进入系统。 2. 在紧急模式下运行&#xff1a;journalctl -xe &#xff0c;查看相关日志&#xff0c;找到关键点&#xff1a; Failed to mount /home 3.接着执行修复命令&#xff1a; xfs_repa…

2024140读书笔记|《作家榜名著:生如夏花·泰戈尔经典诗选》——你从世界的生命的溪流浮泛而下,终于停泊在我的心头

2024140读书笔记|《作家榜名著&#xff1a;生如夏花泰戈尔经典诗选》——你从世界的生命的溪流浮泛而下&#xff0c;终于停泊在我的心头 《作家榜名著&#xff1a;生如夏花泰戈尔经典诗选》[印]泰戈尔&#xff0c;郑振铎译&#xff0c;泰戈尔的诗有的清丽&#xff0c;有的童真&…

lenovo联想ThinkBook 14 G5 ABP(21JE)原装出厂Windows11系统恢复镜像包下载

适用机型 &#xff1a;【21JE】 链接&#xff1a;https://pan.baidu.com/s/1FUjwN8ZeaQ9qr3kNalSkYg?pwdqasf 提取码&#xff1a;qasf 联想原装出厂系统自带所有驱动、出厂主题壁纸、系统属性联机支持标志、系统属性专属LOGO标志、Office办公软件、联想电脑管家、联想浏览…

MySQL 数据类型

数值类型 int类型 类型说明tinyint1字节&#xff0c;范围从-128到127&#xff08;有符号&#xff09;&#xff0c;0到255&#xff08;无符号&#xff09;smallint2字节&#xff0c;范围从-2^15到2^15-1&#xff08;有符号&#xff09;&#xff0c;0到2^16-1&#xff08;无符号…

【WPF】Prism学习(三)

Prism Commands 1.复合命令&#xff08;Composite Commanding&#xff09; 这段内容主要介绍了在应用程序中如何使用复合命令&#xff08;Composite Commands&#xff09;来实现多个视图模型&#xff08;ViewModels&#xff09;上的命令。以下是对这段内容的解释&#xff1a; …

用go语言后端开发速查

文章目录 一、发送请求和接收请求示例1.1 发送请求1.2 接收请求 二、发送form-data格式的数据示例 用go语言发送请求和接收请求的快速参考 一、发送请求和接收请求示例 1.1 发送请求 package mainimport ("bytes""encoding/json""fmt""ne…

SpringCloud Alibaba入门简介和Nacos服务注册和配置中心

前面已经把spring cloud相关的组件都一一学了个遍,现在有点小佩服自己…本来计划今天周末好好出去玩一圈,天气太热了,39了都,还是在办公室学习吧,进行下面的springCloud Alibaba 学习吧…不废话了赶快进入正体 1. SpringCloud Alibaba入门简介 1.1 why会出现SpringCloud alib…

如何让Excel公式中的参数实现动态引用

如果你想成为Excel函数高手&#xff0c;仅仅掌握VLOOKUP和Countif等函数是远远不够的&#xff0c;起码你得学会使用INDIRECT函数&#xff0c;熟练掌握INDIRECT函数能让你从一个初学者晋级为高手&#xff0c;学会它就好比孙悟空掌握了72般变化的基本功&#xff0c;你说厉不厉害。…

【流量分析】常见webshell流量分析

免责声明&#xff1a;本文仅作分享&#xff01; 对于常见的webshell工具&#xff0c;就要知攻善防&#xff1b;后门脚本的执行导致webshell的连接&#xff0c;对于默认的脚本要了解&#xff0c;才能更清晰&#xff0c;更方便应对。 &#xff08;这里仅针对部分后门代码进行流量…

车载诊断架构 --- 关于DTC的开始检测条件

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所有人的看法和评价都是暂时的,只有自己的经历是伴随一生的,几乎所有的担忧和畏惧,都是来源于自己的想象,只有你真的去做了,才会发现有多快乐。…

掌握 Spring Boot 的最佳方法 – 学习路线图

在企业界&#xff0c;人们说“Java 永垂不朽&#xff01;”。但为什么呢&#xff1f;Java 仍然是开发企业应用程序的主要平台之一。大型公司使用企业应用程序来赚钱。这些应用程序具有高可靠性要求和庞大的代码库。根据Java开发人员生产力报告&#xff0c;62% 的受访开发人员使…

《操作系统 - 清华大学》3 -3:连续内存分配:内存碎片与分区的动态分配

文章目录 0. 概述1. 内存碎片问题2. 动态分配3. 首次适配算法4. 最优适配算法5. 最差适配算法 0. 概述 内存分配是操作系统管理过程中很重要的环节&#xff0c;首先需要考虑的是一块连续区域分配的过程&#xff0c;这个过程中会有很多问题&#xff0c;首先比较关注的一个问题是…