外卖项目:使用AOP切面,完成公共字段自动填充(断点调试详细讲解)

文章目录

  • 一、问题描述
  • 二、实现思路
  • 三、实现步骤
  • 四、断点实操
  • 五、代码演示

一、问题描述

我们已经完成了后台系统的员工管理功能菜品分类功能的开发,在新增员工或者新增菜品分类时需要设置创建时间、创建人、修改时间、修改人等字段,在编辑员工或者编辑菜品分类时需要设置修改时间、修改人等字段。这些字段属于公共字段,也就是也就是在我们的系统中很多表中都会有这些字段,如下:

序号字段名含义数据类型
1create_time创建时间datetime
2create_user创建人idbigint
3update_time修改时间datetime
4update_user修改人idbigint

而针对于这些字段,我们的赋值方式为:

1). 在新增数据时, 将createTime、updateTime 设置为当前时间, createUser、updateUser设置为当前登录用户ID。

2). 在更新数据时, 将updateTime 设置为当前时间, updateUser设置为当前登录用户ID。

如果都按照上述的操作方式来处理这些公共字段, 需要在每一个业务方法中进行操作, 编码相对冗余、繁琐,那能不能对于这些公共字段在某个地方统一处理,来简化开发呢?

答案是可以的,我们使用AOP切面编程,实现功能增强,来完成公共字段自动填充功能。

二、实现思路

在实现公共字段自动填充,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免了重复代码。在上述的问题分析中,我们提到有四个公共字段,需要在新增/更新中进行赋值操作, 具体情况如下:

序号字段名含义数据类型操作类型
1create_time创建时间datetimeinsert
2create_user创建人idbigintinsert
3update_time修改时间datetimeinsert、update
4update_user修改人idbigintinsert、update

三、实现步骤

1、自定义注解 AutoFill,用于标识需要进行公共字段自动填充的方法

2、自定义切面类 AutoFillAspect,统一拦截加入了 AutoFill 注解的方法,通过反射为公共字段赋值

3、在 Mapper 的方法上加入 AutoFill 注解

四、断点实操

我们接下来debug一下,先看看update更新数据的情况:

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

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
最后来看看新增员工时的情况:

首先来到controller类:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

五、代码演示

/**
 * 自定义注解,用于标识某个方法需要进行功能字段自动填充处理
 * @Retention(RetentionPolicy.RUNTIME):定义注解的保留策略,
 * 注解会在class字节码文件中存在,在运行时可以通过反射获取到
 * @Target:指定被修饰的Annotation可以放置的位置(被修饰的目标)方法
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
//    数据库操作类型:update、insert
    OperationType value();
}
/**
 * 数据库操作类型
 */
public enum OperationType {
    /**
     * 更新操作
     */
    UPDATE,
    /**
     * 插入操作
     */
    INSERT
}

自定义切面 AutoFillAspect

/**
 * 自定义切面,实现公共字段自动填充处理逻辑
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {

    /**
     * 切入点表达式
     */
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointCut() {
    }

    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint) {
        log.info("开始进行公共字段自动填充...");
        //获取到当前被拦截的方法上的数据库操作类型
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法前面对象
        AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象
        OperationType operationType = autoFill.value();//获得数据库操作类型
        //获取到当前被拦截的方法的参数--实体对象
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            return;
        }
        Object entity = args[0];
        //准备赋值的数据
        Long currentId = BaseContext.getCurrentId();
        LocalDateTime now = LocalDateTime.now();
        //根据当前不同的操作类型,为对应的属性通过反射来赋值
        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) {
                throw new RuntimeException(e);
            }
        } else if (operationType == OperationType.UPDATE) {
            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) {
                throw new RuntimeException(e);
            }
        }
    }
}

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

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

相关文章

西井科技与安通控股签署战略合作协议 共创大物流全新生态

2024年3月21日,西井科技与安通控股在“上海硅巷”新象限空间正式签署战略合作框架协议。双方基于此前在集装箱物流的成功实践与资源优势,积极拓展在AI数字化产品、新能源自动驾驶解决方案和多场景应用,以及绿色物流链等领域的深度探索、强强联…

Pudgy Penguins交易量一路攀升 多次创下历史新高

日前,一个名为胖企鹅(Pudgy Penguins) NFT 项目交易量持续攀升,一度在3月9日成为NFT市场的“销冠”。事实上,从2023年下半年开始,Pudgy Penguins的地板价就在不断上升,进入2024年更是多次创下历…

练习题+题解:链表+dp

目录 1.链表指定区间反转题目描述输入格式:输出格式:输入样例:输出样例:题目分析代码实现 2.hxj和他的甜品盲盒I输入格式:输入样例:输出样例:样例解释 输入样例:输出样例:样例解释 题目分析Java代码实现 3.First 50 Prime Numbers输入格式输出格式输入样例输出样例题目解析代码…

MySQL之索引与事务

一 索引的概念 一种帮助系统查找信息的数据 数据库索引 是一个排序的列表,存储着索引值和这个值所对应的物理地址无须对整个表进行扫描,通过物理地 址就可以找到所需数据是表中一列或者若干列值排序的方法 需要额外的磁盘空间 索引的作用 1 数据库…

【干货】Java开发者快速上手.NET指南

前言 前几天有小伙伴在技术群里发了一个微软官方出的:适用于Java开发人员的.NET快速入门免费电子书,今天大姚来分享一下Java开发者想要快速上手.NET有哪些教程和优质资料。 微软适用于Java开发人员的.NET快速入门指南 下载阅读地址:适用于 …

惟客数据CTO 钱勇:数据资产运营创新和实践

​企业如何做好数据资产运营,有效挖掘和利用数据资产? 近日,在由华东江苏大数据交易中心主办的“第四届数字经济科技大会”上,WakeData惟客数据CTO、星光数智CEO 钱勇 给出了自己的观点。 在演讲环节,钱勇以《数据资…

用tp6写的简单的eml的登录和curd

项目地址&#xff1a; 企业管理eml: 这是一个简单的eml (gitee.com) 1.登录和主页显示 1.1 登录功能逻辑图 1.2 控制器 app/controller/index.php php think make:validate LoginValidate <?php namespace app\controller;use app\BaseController; use app\model\User; …

IDEA设置全局配置

1、 IDEA设置全局配置 在IDEA中&#xff0c;选择 File -> Close Project 关闭项目。然后选择Customize -> All settings 进行全局配置&#xff0c;即所有项目公共的配置。 配置文件编码 配置控制台编码 配置maven 配置文件模板 配置文件模板作者和时间信息如下&#xff…

德勤:《亚太地区半导体行业展望》

2024年2月22日&#xff0c;德勤联合全球半导体联盟&#xff08;GSA&#xff09;对亚洲半导体产业链相关企业展开调研&#xff0c;邀请数位亚太地区主要半导体企业领导人&#xff0c;共同探讨半导体企业在当前环境下应如何通过数字技术曲线的领先优势保持业务竞争力和盈利能力&a…

“我的海外代购,卖起了香灰手串”

【潮汐商业评论/文】 “这个琉璃手串&#xff0c;去年在雍和宫请的&#xff0c;招财的&#xff1b;这个朱砂挂件&#xff0c;当时直播说可以补八字缺火&#xff0c;果断下单的&#xff1b;这个博主讲星座很准&#xff1b;这篇帖子八字说得很详细&#xff1b;我前两天买了‘财神…

qt5-入门-标签页部件QTabWidget-1

参考&#xff1a; C GUI Programming with Qt 4, Second Edition 本地环境&#xff1a; win10专业版&#xff0c;64位&#xff0c;Qt5.12 目录 效果实现Qt Designer操作代码addStretch()解释 效果 首页有三个按钮和最近文件列表。 拖动窗口&#xff0c;按钮和文件列表仍然处…

CentOS7安装mysql-5.7.44单机和主从复制

官网下载地址&#xff1a; https://downloads.mysql.com/archives/community/ 1、单机安装 安装依赖 yum -y install libaio 解压安装 tar -zxvf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gzmv mysql-5.7.44-linux-glibc2.12-x86_64 /usr/local/mysqlcd /usr/local/mysql…

【Spring 篇】走进Java NIO的奇妙世界:解锁高效IO操作的魔法

欢迎来到Java NIO的神奇之旅&#xff01;在这个充满活力的世界里&#xff0c;我们将一起揭示Java NIO&#xff08;New I/O&#xff09;的奥秘&#xff0c;探索其在高效IO操作中的神奇魔法。无需担心&#xff0c;即使你是Java的小白&#xff0c;也能轻松领略这个强大而灵活的IO框…

【pycharm】作为Array查看出现数据无法显示问题(已解决)

【pycharm】作为Array查看出现数据无法显示问题&#xff08;已解决&#xff09; 当我们在调试代码的时候&#xff0c;需要对某个变量进行查看&#xff0c;就如同在matlab中&#xff0c;我们可以直接在工作区对某个变量进行双击查看矩阵变量的具体数值 在这里我遇到一个问题&am…

关于javascript数字精度丢失的解决办法

分析原因 众所周知&#xff0c;在JavaScript中计算两个十进制数的和&#xff0c;有时候会出现令人惊讶的结果&#xff0c;主要原因是计算机将数据存储为二进制所引起的&#xff0c;所以这并不是javascript存在的缺陷&#xff0c;而在其他语言中也有类似的问题。 例如下面的例子…

Java小项目--满汉楼

Java小项目–满汉楼 项目需求 项目实现 1.实现对工具包的编写 先创建libs包完成对jar包的拷贝和添加入库 德鲁伊工具包 package com.wantian.mhl.utils;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource; import java.io.FileInputStream…

Java基础--集合

集合 1.可以动态的保存任意多个对象&#xff0c;使用比较方便。 2.提供了一系列方便的操作对象的方法&#xff1a;add&#xff0c;remove&#xff0c;set&#xff0c;get等。 3.使用集合添加&#xff0c;删除新元素的示意代码&#xff0c;简介明了。 集合主要是两种&#xff0…

c语言扫雷改进版

目录 文章目录 主体 整体架构流程 技术名词解释 技术细节 测试情况 文章目录 概要整体架构流程技术名词解释技术细节测试情况 主体 主体包括菜单&#xff0c;游戏规则简绍&#xff0c;选择进行与否 int main() {int input;srand((unsigned int)time(NULL));do{ menu()…

谷歌地图TMS地图服务地址收集2024,测试可用

对于普通的开发者或者GIS从业者来说&#xff0c;免费的底图影像服务&#xff0c;太重要了。之前写过一篇谷歌地图的TMS地址收集的博文&#xff0c;由于谷歌网站关闭已经不能用。最近又发现了谷歌在国内开放了其他地址&#xff0c;在这里给大家分享一下。 https://gac-geo.googl…

springboot Thymeleaf模版引擎使用

1.引入依赖 <!--thymeleaf视图引擎--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> html中要声明约束&#xff0c;这样就可以使用themelraf视…