操作日志应记录编辑的前后内容变化

news2024/12/23 18:22:04

总体思路是增加一个注解类,将注解加到要进行记录变化的Java类属性上却可。

上代码:

1. 实现注解类: 

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldName {

    String value();

    boolean isIgnoreNull() default false;
}

2. 将注解加到Java类属性

@FieldName("产品编码")
private String productNo;

3. 写一个LogUtil类,对新旧对象进行比较,将变化的内容记录下来,返回List<String>,为了防止异常出现影响正常的业务,用try-catch进行异常处理


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;

import **.FieldName;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
public class LogUtil {

    private static  SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
    /**
     * 记录修改信息
     * @param newObj 更新后数据
     * @param oldObj 更新前数据
     * @param clazz
     * @return
     */
    public static List<String> getUpdateContentList(Object newObj, Object oldObj, Class clazz) {
        List<String> contentList = new ArrayList<>();
        if (newObj == null || oldObj == null) {
            return contentList;
        }

        try {
            //通过hutool BeanUtil工具将实体类转换为Map
            Map newMap = BeanUtil.beanToMap(newObj);
            Map oldMap = BeanUtil.beanToMap(oldObj);

            //通过类对象获取类字段
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                //判断是否有FieldName注解
                if (field.isAnnotationPresent(FieldName.class)) {
                    FieldName fieldName = field.getAnnotation(FieldName.class);
                    //空的和忽略的字段不进行处理
                    if (fieldName.isIgnoreNull() &&  ObjectUtil.isEmpty(newMap.get(field.getName()))) {
                        continue;
                    }
                    String newValue =  newMap.get(field.getName()) == null ? "" : newMap.get(field.getName()).toString();
                    String oldValue =  oldMap.get(field.getName()) == null ? "" : oldMap.get(field.getName()).toString();
                    if(field.getType() == Date.class){
                        try{
                            if(StringUtils.isNotEmpty(newValue)){
                                newValue = formatter.format(newMap.get(field.getName()));
                            }
                            if(StringUtils.isNotEmpty(oldValue)){
                                oldValue = formatter.format(oldMap.get(field.getName()));
                            }
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                    String changeField;
                    Map<String, String> conMap = new HashMap<>();
                    //新旧记录内容不同,说明是修改过,因此记录起来
                    if (!newValue.equals(oldValue)) {
                        //CHANGE_TEXT 自定义拼接内容
                        //CHANGE_TEXT = "fieldName-oldValue --> 调整为 --> fieldName-newValue"
                        String CHANGE_TEXT =  "fieldName:oldValue --> newValue";
                        changeField = CHANGE_TEXT.replaceAll("fieldName", fieldName.value())
                                .replaceAll("oldValue", oldValue)
                                .replaceAll("newValue", newValue);
                        log.info(changeField);
                        contentList.add(changeField);
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        return contentList;
    }
}

LogUtil用到的依赖是:

<dependency>
     <groupId>cn.hutool</groupId>
     <artifactId>hutool-all</artifactId>
     <version>5.7.12</version>
</dependency>

一切准备就结果,接下来就是具体使用:

在Controller类的edit请求中:

// 某个Controller的edit方法中
List<String> updateContentList = getUpdateContentList(product);
String updateContent = "修改产品";
if(!updateContentList.isEmpty()){
     updateContent += ": "+updateContentList;
}
// 日志记录的service类新建一条更新日志
updateRecordService.setProductUpdateRecord(product.getId(), "编辑", updateContent);

/**
  * 获取编辑前后的变化内容
*/
 private List<String> getUpdateContentList(Product product){
     Product oldObject = productService.getById(product.getId());
     return LogUtil.getUpdateContentList(product, oldObject, Product .class);
}

最后的效果如图:

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

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

相关文章

lombok导致的IndexOutOfBoundsException

一、问题描述 ERROR 25152 --- [1.190-81-exec-9] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSyste…

ElementUI Form:Switch 开关

ElementUI安装与使用指南 Switch 开关 点击下载learnelementuispringboot项目源码 效果图 el-switch.vue &#xff08;Switch 开关&#xff09;页面效果图 项目里el-switch.vue代码 <script> export default {name: el_switch,data() {return {value: true,value1: …

Linux内核编译-ARM

步骤一、下载源码及交叉编译器后解压 linux kernel官网 ARM GCC交叉编译器 步骤二、安装软件 sudo apt-get install ncurses-dev sudo apt-get install flex sudo apt-get install bison sudo apt install libgtk2.0-dev libglib2.0-dev libglade2-dev sudo apt install libs…

【wine】Ubuntu 22.04 x86_64 源码编译 wine 9.1 编译版本不能启动微信,apt安装版本可以使用微信

git clone https://gitee.com/winehq/wine.git git checkout wine-9.1 x86_64 注意&#xff08;没有--enable-win32选项&#xff01;&#xff09; sudo apt install build-essential git libtool m4 autoconf automake pkg-config libc6-dev-i386 zlib1g-dev libncurses5-de…

人工智能时代:AI提示工程的奥秘 —— 驾驭大语言模型的秘密武器

文章目录 一、引言二、提示工程与大语言模型三、大语言模型的应用实践四、策略与技巧五、结语《AI提示工程实战&#xff1a;从零开始利用提示工程学习应用大语言模型》亮点内容简介作者简介目录获取方式 一、引言 随着人工智能技术的飞速发展&#xff0c;大语言模型作为一种新…

经典左旋,指针面试题

今天给大家带来几道面试题&#xff01; 实现一个函数&#xff0c;可以左旋字符串中的k个字符。 例如&#xff1a; ABCD左旋一个字符得到BCDA ABCD左旋两个字符得到CDAB 我们可以先自己自行思考&#xff0c;下面是参考答案&#xff1a; 方法一&#xff1a; #define _CRT_SEC…

MongoDB安装以及卸载,通过Navicat 15 for MongoDB连接MongoDB

查询id&#xff1a; docker ps [rootlocalhost ~]# docker stop c7a8c4ac9346 c7a8c4ac9346 [rootlocalhost ~]# docker rm c7a8c4ac9346 c7a8c4ac9346 [rootlocalhost ~]# docker rmi mongo sudo docker pull mongo:4.4 sudo docker images 卸载旧的 sudo docker stop mong…

【脑电信号处理与特征提取】P7-涂毅恒:运用机器学习技术和脑电进行大脑解码

运用机器学习技术和脑电进行大脑解码 科学研究中的大脑解码 比如2019年在Nature上一篇文章&#xff0c;来自UCSF的Chang院士的课题组&#xff0c;利用大脑活动解码语言&#xff0c;帮助一些患者恢复语言功能。 大脑解码的重要步骤 大脑解码最重要的两步就是信号采集和信号…

【Linux】Daemon守护进程详解

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;Linux系列专栏&#xff1a;Linux基础 &#x1f525; 给大家…

JAVASE进阶:String常量池内存原理分析、字符串输入源码分析

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;JAVASE进阶&#xff1a;内存原理剖析&#xff08;1&#xff09;——数组、方法、对象、this关键字的内存原理 &#x1f4da;订阅…

嵌入式人工智能/深度学习/神经网络导论

加我微信hezkz17进入嵌入式人工智能技术研究开发交流答疑群 1 嵌入式人工智能&#xff0c;嵌入式深度学习含义&#xff1f; &#xfffc; 嵌入式人工智能&#xff08;Embedded Artificial Intelligence&#xff09;是指将人工智能技术应用于嵌入式系统中&#xff0c;使其具备…

计算机网络_1.4 计算机网络的定义和分类

1.4 计算机网络的定义和分类 一、计算机网络的定义&#xff08;无唯一定义&#xff09;二、计算机网络的分类&#xff08;从不同角度分类&#xff09;1、交换方式2、使用者3、传输介质4、覆盖范围5、拓扑结构 笔记来源&#xff1a; B站 《深入浅出计算机网络》课程 一、计算机…

11张宝藏GIS开发思维导图,重点清晰,建议带走!

在GIS开发过程中&#xff0c;涉及大量的数据、地图、工具和技术。通过思维导图&#xff0c;我们可以将这些复杂的元素进行可视化&#xff0c;更好地理解和整理思路&#xff0c;提高开发效率。 同时思维导图利用了色彩、线条、关键词、图像等元素&#xff0c;可以加强记忆的可能…

Android平台如何实现RTSP转GB28181

为什么要做GB28181设备接入侧&#xff1f; 实际上&#xff0c;在做Android平台GB28181设备接入模块的时候&#xff0c;我们已经有了非常好的技术积累&#xff0c;比如RTMP推送、轻量级RTSP服务、一对一互动模块、业内几乎最好的RTMP|RTSP低延迟播放器。 Android平台GB28181接…

好书推荐丨保姆级Midjourney教程,这本写给大家看的设计书闭眼入!

文章目录 写在前面好书推荐Part.1Part.2Part.3 粉丝福利写在后面 写在前面 在AI绘画界&#xff0c;有每日经典一问&#xff1a;“你今天用Midjourney画了啥&#xff1f;”晒作品成为重头戏。 小红书上关于Midjourney出的图片点赞数惊人。 reddit上的恶搞幽默图片热度居高不下…

C#,幸运数字(Lucky Number)的算法与源代码

Lucky Number不是蔡依林的歌曲名字哦。 给你的NV朋友选一个幸运数字吧。 1 幸运数字是怎么产生的&#xff1f; 幸运数是整数的子集。与其进行大量理论研究&#xff0c;不如让我们来看看得出幸运数字的过程&#xff0c; 以整数集为例&#xff1a; 1,2,3,4,5,6,7,8,9,10,11,…

NAT 机制的工作流

NAT机制&#xff08;网络地址映射&#xff09;先把IP地址分成两个大类 1. 私网IP / 局域网IP 2. 公网IP / 广域网IP 要求公网的设备&#xff0c;对应的公网IP&#xff0c;都必须是唯一的&#xff0c;但是私网上/局域网上的设备&#xff0c;使用私网IP&#xff0c;只要保证局域网…

Linux 网络配置及基础服务

目录 一. 查看网络配置信息的相关命令 1.1 ifconfig 命令 作用 1&#xff1a; 作用 2&#xff1a; 拓展&#xff1a; 1.2 ip/ethtool命令 1.3 hostname命令 1.4 route 命令 1.5 netstat 命令 1.6 ss&#xff08;socket statistics&#xff09;命令 1.7 ping 命令 …

vscode 插件 Tailwind CSS IntelliSense 解决 class 提示问题

问题描述&#xff1a; 如下写js字符串是没有class智能提示的&#xff1a; const clsName bg-[#123456] text-[#654321] return <div className{clsName}></div>解决方案&#xff1a; 安装 clsx 依赖 pnpm i clsx设置 vscode 的 settings.json {"tailwin…

【C++】开源:Windows图形库EasyX配置与使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍Windows图形库EasyX配置与使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#…