【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.rhkb.cn/news/472886.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络安全练习之 ctfshow_web

文章目录 VIP题目限免&#xff08;即&#xff1a;信息泄露题&#xff09;源码泄露前台JS绕过协议头信息泄露robots后台泄露phps源码泄露源码压缩包泄露版本控制泄露源码(git)版本控制泄露源码2(svn)vim临时文件泄露cookie泄露域名txt记录泄露敏感信息公布内部技术文档泄露编辑器…

Git_2024/11/16

文章目录 前言Git是什么核心概念工作流程常见术语解读Git的优势 Git与SVN对比SVNGit总结 Git配置流程及指令环境配置获取Git仓库本地初始化远程克隆 工作目录、暂存区、版本库文件的两种状态本地仓库操作远程仓库操作Git分支Git标签IntelliJ IDEA使用Git回滚代码 GitHub配置流程…

游戏引擎学习第八天

视频参考: https://www.bilibili.com/video/BV1ouUPYAErK/ 理解下面的代码 关于虚函数 代码分解 结构体 foo 的定义&#xff1a; struct foo {int32 X;int64 Y;virtual void Bar(int c); };foo 结构体有两个成员变量&#xff1a;X&#xff08;int32 类型&#xff09;和 Y&…

蓝桥杯-洛谷刷题-day3(C++)

目录 1.忽略回车的字符串输入 i.getline() ii.逐个字符的识别再输入 2.获取绝对值abs() 3.做题时的误区 4.多个变量的某一个到达判断条件 i.max() 5.[NOIP2016 提高组] 玩具谜题 i.代码 6.逻辑上的圆圈 i.有限个数n的数组 7.数组的定义 i.动态数组 1.忽略回车的字符串输…

不用来回切换,一个界面管理多个微信

你是不是也有多个微信号需要管理&#xff1f; 是不是也觉得频繁切换账号很麻烦&#xff1f; 是不是也想提升多账号管理的效率&#xff1f; 在工作中&#xff0c;好的辅助工具&#xff0c;能让我们的效率加倍增长&#xff01; 今天&#xff0c; 就给大家分享一个多微管理工具…

Word_小问题解决_1

1.第二页是空白的&#xff0c;但是删不掉 将鼠标弄到第二页最开始的地方打开段落设置行距为固定值0.7磅 2.表格中有文字进入了表格中怎么办 打开段落&#xff0c;将缩进改为0即可

LLM - 计算 多模态大语言模型 的参数量(Qwen2-VL、Llama-3.1) 教程

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/143749468 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 影响 (…

GEE下载ERA5-Land气象数据(1950-至今,降水、温度)

GEE下载ERA5-Land气象数据&#xff08;1950-至今&#xff0c;降水、温度&#xff09; ERA5-Land是一个高分辨率的陆地再分析数据集,相比ERA5数据集具有更高的空间分辨率。它是通过重新运行ECMWF ERA5气候再分析系统的陆地分量生成的。 空间分辨率特点&#xff1a; 网格间距…

动态规划-完全背包问题——518.零钱兑换II

1.题目解析 建议先看 322.零钱兑换可以 更加轻松的理解本题 题目来源 518.零钱兑换——力扣 测试用例 2.算法原理 1.状态表示 本题要求返回所有情况&#xff0c;所以dp值就代表所有的方法数&#xff0c;即 dp[i][j]&#xff1a;在[1,i]个硬币中选择不同面值的硬币&#xff0c…

推荐15个2024最新精选wordpress模板

以下是推荐的15个2024年最新精选WordPress模板&#xff0c;轻量级且SEO优化良好&#xff0c;适合需要高性能网站的用户。中文wordpress模板适合搭建企业官网使用。英文wordpress模板&#xff0c;适合B2C网站搭建&#xff0c;功能强大且兼容性好&#xff0c;是许多专业外贸网站的…

使用Java绘制图片边框,解决微信小程序map组件中marker与label层级关系问题,label增加外边框后显示不能置与marker上面

今天上线的时候发现系统不同显示好像不一样&#xff0c;苹果手机打开的时候是正常的&#xff0c;但是一旦用安卓手机打开就会出现label不置顶的情况。尝试了很多种办法&#xff0c;也在官方查看了map相关的文档&#xff0c;发现并没有给label设置zIndex的属性&#xff0c;只看到…

微信小程序 https://thirdwx.qlogo.cn 不在以下 downloadFile 合法域名列表中

授权登录后&#xff0c;拿到用户头像进行加载&#xff0c;但报错提示&#xff1a; https://thirdwx.qlogo.cn 不在以下 downloadFile 合法域名列表中 解决方法一&#xff08;未完全解决&#xff0c;临时处理&#xff09;&#xff1a;在微信开发者工具将不校验...勾上就可以访问…

【HAProxy09】企业级反向代理HAProxy高级功能之压缩功能与后端服务器健康性监测

HAProxy 高级功能 介绍 HAProxy 高级配置及实用案例 压缩功能 对响应给客户端的报文进行压缩&#xff0c;以节省网络带宽&#xff0c;但是会占用部分CPU性能 建议在后端服务器开启压缩功能&#xff0c;而非在HAProxy上开启压缩 注意&#xff1a;默认Ubuntu的包安装nginx开…

zabbix7.0实操指南:基于麒麟V10操作系统部署zabbix7.0

在当今信息技术飞速发展的时代&#xff0c;企业对于IT基础设施的监控管理需求日益增长。为了确保系统的稳定性和高效性&#xff0c;我们需要一个强大的监控工具来实时监控各种硬件和软件资源的状态。Zabbix作为一个开源的企业级监控解决方案&#xff0c;因其强大的功能和灵活的…

Android笔记(三十七):封装一个RecyclerView Item曝光工具——用于埋点上报

背景 项目中首页列表页需要统计每个item的曝光情况&#xff0c;给产品运营提供数据报表分析用户行为&#xff0c;于是封装了一个通用的列表Item曝光工具&#xff0c;方便曝光埋点上报 源码分析 核心就是监听RecyclerView的滚动&#xff0c;在滚动状态为SCROLL_STATE_IDLE的时…

微服务瞎写

1.微服务解决的问题 1、如何发现新节点以及检查各节点的运行状态&#xff1f; 2、如何发现服务及负载均衡如何实现&#xff1f; 3、服务间如何进行消息通信&#xff1f; 4、如何对使用者暴露服务API&#xff1f; 5、如何集中管理各节点配置文件&#xff1f; 6、如何收集各…

群控系统服务端开发模式-应用开发-前端图片格式功能开发

一、添加视图 在根目录下src文件夹下views文件夹下param文件夹下grade文件夹下&#xff0c;新建index.vue&#xff0c;代码如下 <template><div class"app-container"><div class"filter-container" style"float:left;"><…

创建vue+electron项目流程

一个vue3和electron最基本的环境搭建步骤如下&#xff1a;// 安装 vite vue3 vite-plugin-vue-setup-extend less normalize.css mitt pinia vue-router npm create vuelatest npm i vite-plugin-vue-setup-extend -D npm i less -D npm i normalize.css -S &#xff0…

Android Studio 控制台输出的中文显示乱码

1. Android Studio 控制台输出的中文显示乱码 1.1. 问题 安卓在调试阶段&#xff0c;需要查看app运行时的输出信息、出错提示信息。乱码&#xff0c;会极大的阻碍开发者前进的信心&#xff0c;不能及时的根据提示信息定位问题&#xff0c;因此我们需要查看没有乱码的打印信息。…

常见的测试方法

软件测试是软件⽣命周期中的⼀个重要环节&#xff0c;具有较⾼的复杂性&#xff0c;对于软件测试&#xff0c;可以从不同的⻆度加以分类&#xff0c;使开发者在软件开发过程中的不同层次、不同阶段对测试⼯作进⾏更好的执⾏和管理测试的分类⽅法。 按照测试目标分类 界面测试…