Spring AOP + 自定义注解 实现公共字段的填充

Spring AOP + 自定义注解 实现公共字段的填充

在这里插入图片描述

代码冗,不利于后期维护.

定义操作这些字段的方法类型

在这里插入图片描述

实现步骤:

  • 自定义注解AutoFill,用于表示操作这些公共字段的方法
  • 自定义切面类AutoFillAspect,统一拦截,通过反射获取方法入参,并填充公共字段
  • 在Mapper的insert、update的方法上加上自定义的AutoFill注解

代码:

- 不使用mybatis-plus自带的填充注解

必要依赖

 <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.7</version>
</dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.1.0</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.11</version>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.7.5</version>
</dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.18</version>
</dependency>

1、自定义注解AutoFill,用于表示操作这些公共字段的方法

import com.cwh.mpdemo.enums.OpreaType;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定义注解,表示方法*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {/*** 操作类型** @return*/OpreaType value() default OpreaType.INSERT;
}

2、自定义切面类AutoFillAspect,统一拦截,通过反射获取方法入参,并填充公共字段


import com.cwh.mpdemo.annotation.AutoFill;
import com.cwh.mpdemo.enums.OpreaType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;/*** @Aspect 标注为切面类*/
@Aspect
@Component
@Slf4j
public class AutoFillaspect {// 定义切点@Pointcut("execution(* com.cwh.mpdemo.mapper.*.*(..)) && @annotation(com.cwh.mpdemo.annotation.AutoFill)")public void pointcut(){}// 定义通知@Before("pointcut()")public void before(JoinPoint joinPoint){log.info("auto fill start...");MethodSignature signature = (MethodSignature) joinPoint.getSignature();AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);OpreaType value = annotation.value();//获取签名方法的入参Object[] args = joinPoint.getArgs();if (args.length ==0 ||args == null)  {return;}Object arg = args[0];try {// 填充字段if (value == OpreaType.INSERT){//通过反射给入参对象的字段赋值arg.getClass().getDeclaredMethod("setCreateTime", Date.class).invoke(arg, Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC)));//实际中从ThreadLocal获取用户id          arg.getClass().getDeclaredMethod("setCreateUser",String.class).invoke(arg,"test");} arg.getClass(). getDeclaredMethod("setUpdateTime",Date.class).invoke(arg,Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC)));//实际中从ThreadLocal获取用户idarg.getClass().getDeclaredMethod("setUpdateUser",String.class).invoke(arg,"test");}catch (Exception exception){log.error("auto fill error:{}",exception.getMessage());}log.info("auto fill end...");}
}
public enum OpreaType {INSERT,UPDATE;
}

3、在Mapper的insert、update的方法上加上自定义的AutoFill注解

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cwh.mpdemo.annotation.AutoFill;
import com.cwh.mpdemo.domain.SessionDomain;public interface SessionLoginMapper extends BaseMapper<SessionDomain> {@AutoFillvoid insertData(SessionDomain sessionDomain);
}

- 使用mybatis-plus自带的填充注解

首先在实体对象上加自动填充属性注解fill = FieldFill.INSERT

@Data
@TableName("session_login")
public class SessionDomain {@TableId(value = "id", type = IdType.AUTO)private Long id;@TableFieldprivate String userName;@TableField(fill = FieldFill.INSERT)private Date createTime;@TableField(fill = FieldFill.INSERT)private String createUser;@TableField(fill = FieldFill.UPDATE)private Date updateTime;@TableField(fill = FieldFill.UPDATE)private String updateUser;
}

实现元数据对象处理器接口MetaObjectHandler,实现insertFill,updateFill逻辑

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;@Component
public class AutoFillHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {// 设置属性值this.setFieldValByName("createTime", Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC)), metaObject);this.setFieldValByName("updateTime", Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC)), metaObject);//实际中从ThreadLocal获取用户idthis.setFieldValByName("createUser", "1", metaObject);this.setFieldValByName("updateUser", "1", metaObject);}@Overridepublic void updateFill(MetaObject metaObject) {//实际中从ThreadLocal获取用户idthis.setFieldValByName("updateTime", Date.from(LocalDateTime.now().toInstant(ZoneOffset.UTC)), metaObject);this.setFieldValByName("updateUser", "1", metaObject);}
}	

剩下就是在service层使用mapper接口insert、update数据即可。

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

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

相关文章

【THM】Burp Suite:Other Modules(其他模块)-初级渗透测试

介绍 除了广泛认可的Repeater和Intruder房间之外,Burp Suite 还包含几个鲜为人知的模块。这些将成为这个房间探索的重点。 重点将放在解码器、比较器、排序器和组织器工具上。它们促进了编码文本的操作,支持数据集的比较,允许分析捕获的令牌内的随机性,并帮助您存储和注释…

9、鸿蒙学习-开发及引用静态共享包(API 9)

HAR&#xff08;Harmony Archive&#xff09;是静态共享包&#xff0c;可以包含代码、C库、资源和配置文件。通过HAR可以实现多个模块或多个工程共享ArkUI组件、资源等相关代码。HAR不同于HAP&#xff0c;不能独立安装运行在设备上&#xff0c;只能作为应用模块的依赖项被引用。…

MongoDB 6.1 及以上版本使用配置文件的方式启动报错 Unrecognized option: storage.journal.enabled

如果你使用的 MongoDB 的版本大于等于 6.1&#xff0c;并且在 MongoDB 的配置文件中编写了如下内容 storage:journal:# 启用或禁用持久性日志以确保数据文件保持有效和可恢复# true 启用&#xff1b;false 不启用# 64 位系统默认启用&#xff0c;启用后 MongoDB 可以在宕机后根…

Linux多进程通信(1)——无名管道及有名管道使用例程

管道是半双工通信&#xff0c;如果需要 双向通信&#xff0c;则需要建立两个管道&#xff0c; 无名管道&#xff1a;只能父子进程间通信&#xff0c;且是非永久性管道通信结构&#xff0c;当它访问的进程全部终止时&#xff0c;管道也随之被撤销 有名管道&#xff1a;进程间不需…

RK3568驱动指南|第十四篇 单总线-第162章DS18B20驱动读时序编写

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

Golang 开发实战day06 - Boolean Conditional

Golang 教程06 - Boolean & Conditional 1. Boolean & Conditional 1.1 什么是布尔类型&#xff1f; 想象一下&#xff0c;你正在玩一个古老的游戏&#xff0c;只有两个选项&#xff1a;是或否。在 Golang 中&#xff0c;这就是布尔类型&#xff0c;用 bool 关键字表…

【Linux实验室】DNS域名解析服务——超详细实验操作!

DNS域名解析 DNS域名解析服务——超详细实验操作&#xff01;&#xff01;&#xff01;序言DNS 基本概述分布式、层次数据库DNS 层次结构DNS 查询步骤DNS 查询类型DNS服务器类型DNS 缓存反向 DNS 查询如何检查 DNS 记录是否生效 Bind解析服务Bind简介bind的服务类型 DNS域名解析…

深入解析实时数仓Doris:Rollup上卷表与查询

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 目录 一、基本概念二、Aggregate 和 Unique 模型中的 ROLLUP三、Duplicate 模型中的 ROLLUP四、ROLLUP 调整前缀索引五、ROLLUP使…

【深耕 Python】Data Science with Python 数据科学(7)书352页练习题

写在前面 关于数据科学环境的建立&#xff0c;可以参考我的博客&#xff1a; 【深耕 Python】Data Science with Python 数据科学&#xff08;1&#xff09;环境搭建 往期数据科学博文&#xff1a; 【深耕 Python】Data Science with Python 数据科学&#xff08;2&#xf…

每日面经分享(pytest测试案例,接口断言,多并发断言)

pytest对用户登录接口进行自动化脚本设计 a. 创建一个名为"test_login.py"的测试文件&#xff0c;编写以下测试脚本 import pytest import requests# 测试用例1&#xff1a;验证登录成功的情况 # 第一个测试用例验证登录成功的情况&#xff0c;发送有效的用户名和密…

iOS系统文件备份与还原:保护和管理手机中的关键数据

​ 目录 引言 用户登录工具和连接设备 查看设备信息&#xff0c;电池信息 查看硬盘信息 硬件信息 查看 基带信息 销售信息 电脑可对手机应用程序批量操作 运行APP和查看APP日志 IPA包安装测试 注意事项 引言 苹果手机与安卓手机不同&#xff0c;无法直接访问系统文件…

Chatgpt掘金之旅—有爱AI商业实战篇|文案写作|(三)

演示站点&#xff1a; https://ai.uaai.cn 对话模块 官方论坛&#xff1a; www.jingyuai.com 京娱AI 一、前言 人工智能&#xff08;AI&#xff09;技术作为当今科技创新的前沿领域&#xff0c;为创业者提供了广阔的机会和挑战。随着AI技术的快速发展和应用领域的不断拓展&…

是否应该升级到ChatGPT 4.0?深度对比ChatGPT 3.5与4.0的差异

如果只是想简单地体验AI的魅力&#xff0c;感受大模型的独特之处&#xff0c;或是玩一玩文字游戏&#xff0c;那么升级至ChatGPT 4.0可能并非必需。然而&#xff0c;若你期望将AI作为提升工作学习效率的得力助手&#xff0c;那么我强烈建议你升级到ChatGPT 4.0。 如果你不知道…

Linux和Windows安装PHP依赖管理工具Composer

Composer 是 PHP 的一个依赖管理工具。它允许申明项目所依赖的代码库&#xff0c;会在项目中安装它们。 Composer 不是一个包管理器。是的&#xff0c;它涉及 "packages" 和 "libraries"&#xff0c;但它在每个项目的基础上进行管理&#xff0c;在你项目的…

【Springboot整合系列】SpringBoot整合WebService

目录 Web服务介绍Web服务的两种类型Web服务架构Web服务的主要特点Web服务使用场景Web服务标准和技术 WebService介绍WebService的作用适用场景不适用场景 WebService的原理三个角色相关概念 WebService开发框架代码实现服务端1.引入依赖2.实体类3.业务层接口接口实现类 4.配置类…

python对接百度云车牌识别

注册百度智能云&#xff0c;选择产品服务。 https://console.bce.baidu.com/ 每天赠送200次&#xff0c;做开发测试足够了。 在应用列表复制 AppID , API Key ,Secret Key 备用。 SDK下载地址 https://ai.baidu.com/sdk#ocr 下载SDK文件&#xff0c;解压&#xff0c;…

matlab中旋转矩阵函数

文章目录 matlab里的旋转矩阵、四元数、欧拉角四元数根据两向量计算向量之间的旋转矩阵和四元数欧拉角转旋转矩阵旋转矩阵转欧拉角旋转矩阵转四元数参考链接 matlab里的旋转矩阵、四元数、欧拉角 旋转矩阵dcmR四元数quatq[q0,q1,q2,q3]欧拉角angle[row,pitch,yaw] % 旋转矩阵…

前端跨页面通信方案介绍

在浏览器中&#xff0c;我们可以同时打开多个Tab页&#xff0c;每个Tab页可以粗略理解为一个“独立”的运行环境&#xff0c;即使是全局对象也不会在多个Tab间共享。然而有些时候&#xff0c;我们希望能在这些“独立”的Tab页面之间同步页面的数据、信息或状态。这就是本文说说…

算法学习——LeetCode力扣动态规划篇2(343. 整数拆分、96. 不同的二叉搜索树、416. 分割等和子集、1049. 最后一块石头的重量 II)

算法学习——LeetCode力扣动态规划篇2 343. 整数拆分 343. 整数拆分 - 力扣&#xff08;LeetCode&#xff09; 描述 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得…

构建第一个JS应用(FA模型)

创建JS工程 若首次打开DevEco Studio&#xff0c;请点击Create Project创建工程。如果已经打开了一个工程&#xff0c;请在菜单栏选择File > New > Create Project来创建一个新工程。选择Application应用开发&#xff08;本文以应用开发为例&#xff0c;Atomic Service对…