公共字段自动填充——后端
场景:当处理一些请求时,会重复的对数据库的某些字段进行赋值(如:在插入和更新某个物品时,需要更新该物品的更新时间和更新者的信息),这样会导致代码冗余。
如:

思路:
- 自定义注解 AutoFill,用于标识需要进行公共字段自动填充的方法
- 自定义切面类 AutoFillAspect,统一拦截加入了 AutoFill 注解的方法,通过反射为公共字段赋值
- 在 Mapper 的方法上加入 AutoFill 注解
实现:
定义AutoFill注解:
package com.sky.annotation;import com.sky.enumeration.OperationType;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** ClassName: AufoFill* PackageName: com.sky.Annotation* Description: 用于表示某个方法需要进行功能字段自动填充处理** @Author Xiyan Zhong* @Create 2023/12/18 下午2:55* @Version 1.0*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {// 数据库操作类型:UPDATE INSERTOperationType value();
}
实现切面类:
package com.sky.aspect;import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
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.lang.reflect.Method;
import java.time.LocalDateTime;/*** ClassName: AutoFillAspect* PackageName: com.sky.Aspect* Description:自定义切面,实现公共字段自动填充逻辑** @Author Xiyan Zhong* @Create 2023/12/18 下午3:00* @Version 1.0*/@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 annotation = signature.getMethod().getAnnotation(AutoFill.class);// 获取方法上的注解对象OperationType operationType = annotation.value(); // 获取数据库操作类型// 获取到当前被拦截方法的参数——实体对象Object[] args = joinPoint.getArgs();if (args == null || args.length == 0) {return;}Object entity = args[0];// 准备赋值的数据LocalDateTime now = LocalDateTime.now();Long currentId = BaseContext.getCurrentId();// 根据当前不同的操作类型,为对应的属性通过反射来赋值if (operationType == OperationType.INSERT) {//try {Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME ,LocalDateTime.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);// 通过反射为对象属性赋值setCreateTime.invoke(entity,now);setCreateUser.invoke(entity,currentId);setUpdateTime.invoke(entity,now);setUpdateUser.invoke(entity,currentId);} catch (Exception e) {e.printStackTrace();}} else if (operationType == OperationType.UPDATE) {try {// 为2个公共字段赋值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();}}}
}
需要注意的是,在反射中获取方法名时和判断拦截方法的类型时,分别采用的是常量和枚举,而不是直接使用方法的字符串名称,这样可以降低编码时的错误率,也更加规范,对应的代码:
package com.sky.constant;/*** 公共字段自动填充相关常量*/
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";
}
/*** 数据库操作类型*/
package com.sky.enumeration;/*** 数据库操作类型*/
public enum OperationType {/*** 更新操作*/UPDATE,/*** 插入操作*/INSERT}
在Mapper对应的方法中,添加注解@AutoFill:
/*** 插入数据* @param category*/@Insert("insert into category(type, name, sort, status, create_time, update_time, create_user, update_user) " +" values" +"(#{type}, #{name},#{sort},#{status},#{createTime},#{updateTime},#{createUser},#{updateUser})")@AutoFill(OperationType.INSERT)void insert(Category category);/*** 根据id修改分类* @param category*/@AutoFill(OperationType.UPDATE)void update(Category category);
删除对应的服务实现类的赋值操作。
相关文章:
公共字段自动填充——后端
场景:当处理一些请求时,会重复的对数据库的某些字段进行赋值(如:在插入和更新某个物品时,需要更新该物品的更新时间和更新者的信息),这样会导致代码冗余。 如: 思路: 自…...
nginx upstream 6种负载均衡策略介绍
upstream参数 参数描述service反向服务地址加端口weight权重max_fails失败多少次,认为主机已经挂掉,踢出fail_timeout踢出后重新探测时间backup备用服务max_conns允许最大连接数slow_start当节点恢复,不立即加入 负载均衡策略 轮询&#x…...
基于Antd4 和React-hooks的项目开发
基于Antd4 和React-hooks的项目开发 https://github.com/dL-hx/react-cnode 项目依赖使用 react 16.13react-redux 7.xreact-router-dom 5.xredux 4.xantd 4axiosmoment 2.24 (日期格式化)qs 项目视图说明 首页主题详情用户列表用户详情关于 配置按需加载 https://3x.an…...
Spring中用到的设计模式
一、工厂模式 BeanFactory 1、简单工厂模型,是指由一个工厂对象决定创建哪一种产品类的实例,工厂类负责创建的对象较少,客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需要关心 优点: 只需传入一个正确的参数…...
常用网络接口自动化测试框架
(一)GUI界面测试工具:jmeter 1、添加线程组 2、添加http请求 3、为线程组添加察看结果树 4、写入接口参数并运行 5、在查看结果树窗口查看结果 6、多组数据可增加CSVDataSetConfig(添加.csv格式的文件,并在参数值里以${x}格式写入) 此时变量…...
【重点】【贪心】55.跳跃游戏
题目 法1:贪心 class Solution {public boolean canJump(int[] nums) {int maxIndex nums.length - 1;int curMaxIndex 0;for (int i 0; i < nums.length; i) {if (i < curMaxIndex) {curMaxIndex Math.max(i nums[i], curMaxIndex);if (curMaxIndex &…...
灰度化、二值化、边缘检测、轮廓检测
灰度化 定义 灰度图像是只含亮度信息,不含色彩信息的图像。灰度化处理是把彩色图像转换为灰度图像的过程,是图像处理中的基本操作。OpenCV 中彩色图像使用 BGR 格式。灰度图像中用 8bit 数字 0~255 表示灰度,如:0 表…...
基于JAVA的高校大学生创业管理系统 开源项目
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统公告模块2.2 创业项目模块2.3 创业社团模块2.4 政府政策模块2.5 创业比赛模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 系统公告表3.2.2 创业项目表3.2.3 创业社团表3.2.4 政策表 四、系统展示五、核心代码5.…...
神经网络学习小记录76——Tensorflow2设置随机种子Seed来保证训练结果唯一
神经网络学习小记录76——Tensorflow2设置随机种子Seed来保证训练结果唯一 学习前言为什么每次训练结果不同什么是随机种子训练中设置随机种子 学习前言 好多同学每次训练结果不同,最大的指标可能会差到3-4%这样,这是因为随机种子没有设定导致的&#x…...
ai学习笔记-入门
目录 一、人工智能是什么?可以做什么? 人工智能(Artificial Intelligence): 人工智能的技术发展路线: 产业发展驱动因素:数据、算力、算法 二、人工智能这个工具的使用原理入门 神经网络⭕数学基础 1.神经网络的生物表示 …...
workflow系列教程(5-1)HTTP Server
往期教程 如果觉得写的可以,请给一个点赞关注支持一下 观看之前请先看,往期的博客教程,否则这篇博客没办法看懂 workFlow c异步网络库编译教程与简介 C异步网络库workflow入门教程(1)HTTP任务 C异步网络库workflow系列教程(2)redis任务 workflow系列教程(3)Series串联任务流…...
php-使用wangeditor实现富文本(完成图片上传)-npm
官网参考连接:快速开始 | wangEditor 样式: 一、新建一个临时文件夹test1和一个文件夹wangeditor 临时文件夹test1:临时存放通过npm下载的文件文件夹wangeditor:用于存放在临时文件夹test1拷贝的css和js 二、安装 editor 在确保有…...
mysql查看数据库中所有的表的建表语句
mysql查看数据库中所有的表: SHOW TABLES; 这条命令将返回数据库中所有表的列表。 如果要查看单个表的建表语句,可以使用以下命令: SHOW CREATE TABLE table_name; 其中,"table_name"为你要查看的表的名称。 如果…...
【Axure RP9】实现登入效验及实现左侧菜单栏跳转各页面
目录 一 效验简介 1.1 校验好处 1.2 应用场景 二 登入校验 2.1 效果 2.2 实现流程 三 左边菜单栏左侧菜单栏跳转各页面 3.1 效果 3.2 实现图 一 效验简介 1.1 校验好处 提高安全性: 在传统的用户名和密码登录的基础上,引入了另一种或多种验证…...
76. 最小覆盖子串。优化官方题解!
leetcode原题如下: 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。 注意: 对于 t 中重复字符,我们寻找的子字符串中该字符数量…...
在国产GPU寒武纪MLU上快速上手Pytorch使用指南
本文旨在帮助Pytorch使用者快速上手使用寒武纪MLU。以代码块为主,文字尽可能简洁,许多部分对标NVIDIA CUDA。不正确的地方请留言更正。本文不定期更新。 文章目录 前言Cambricon PyTorch的Python包torch_mlu导入将模型加载到MLU上model.to(mlu)定义损失函…...
重生奇迹MU觉醒战士攻略
剑士连招技巧:生命之光:PK前起手式,增加血上限。 雷霆裂闪:眩晕住对手,剑士PK战士第一技能,雷霆裂闪是否使用好关系到胜负。 霹雳回旋斩:雷霆裂闪后可以选择用霹雳回旋斩跑出一定范围(因为对手…...
美颜技术详解:深入了解视频美颜SDK的工作机制
本文将深入探讨视频美颜SDK的工作机制,揭示其背后的科技奥秘和算法原理。 1.引言 视频美颜SDK作为一种集成到应用程序中的技术工具,通过先进的算法和图像处理技术,为用户提供令人印象深刻的实时美颜效果。 2.视频美颜SDK的基本工作原理 首…...
3D模型格式转换工具如何实现高性能数据转换?请看CAE系统开发实例!
客户背景 DP Technology是全球知名的CAM的供应商,在全球8个国家设有18个办事处。DP Technology提供的CAMESPRIT系统是一个用于数控编程,优化和仿真全方面的CAM系统。CAMESPRIT的客户来自多个行业,因此支持多种CAD工具和文件格式显得格外重…...
多级缓存:亿级流量的缓存方案
文章目录 一.多级缓存的引入二.JVM进程缓存三.Lua语法入门四.多级缓存1.OpenResty2.查询Tomcat3.Redis缓存预热4.查询Redis缓存5.Nginx本地缓存6.缓存同步 一.多级缓存的引入 传统缓存的问题 传统的缓存策略一般是请求到达Tomcat后,先查询Redis,如果未…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
