对象比较工具类:实现对业务的修改记录保存(对象字段差异对比)

测试

1:User类 

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {@FieldLabel("姓名")private String name;@FieldLabel("年龄")private Integer age;@FieldLabel("手机")private String phone;@FieldLabel("手机号")private String phoneNumber;@Nullableprivate Address address;
}

2:自定义注解

import java.lang.annotation.*;@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface FieldLabel {String value(); // 中文标识
}

3:工具类

依赖:
        <!-- google java lib --><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>17.0</version></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.5</version></dependency>

utils:

package com.example.juc.utils.比较对象的差异工具类;import com.google.gson.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.converter.json.GsonFactoryBean;import java.util.*;/*** @author: xlj* @create: 2024-10-09 15:29* @description: 对象比较工具类*/
@Slf4j
public class ModelDiffUtil {private static final Gson gson = new Gson();private final static String SOURCE_VALUE = "source";private final static String TARGET_VALUE = "target";private final static String DOT_SEPARATOR = ".";/*** 将两个对象的差异转换为Map格式。** @param sourceObject  原始对象* @param targetObject 当前对象* @return 包含差异的Map*/public static<T> Map<String, Map<String, String>> getDiffMap(T sourceObject, T targetObject) {return getDiffMap(sourceObject, targetObject, null);}/*** 将两个对象的差异转换为Map格式,可以指定忽略的字段。** @param sourceObject  原始对象* @param targetObject 当前对象* @param ignoreFields  忽略的字段列表* @return 包含差异的Map*/public static <T> Map<String, Map<String, String>> getDiffMap(T sourceObject, T targetObject, List<String> ignoreFields) {try {String sourceJsonStr = gson.toJson(sourceObject);String targetJsonStr = gson.toJson(targetObject);return getDiffMap(sourceJsonStr, targetJsonStr, ignoreFields);} catch (JsonSyntaxException e) {log.error("Failed to parse object to JSON", e);return new HashMap<>();}}/*** 从JSON字符串中提取差异。** @param sourceJsonStr  原始JSON字符串* @param targetJsonStr 当前JSON字符串* @return 包含差异的Map*/public static Map<String, Map<String, String>> getDiffMap(String sourceJsonStr, String targetJsonStr) {return getDiffMap(sourceJsonStr, targetJsonStr, null);}/*** 从JSON字符串中提取差异,可以指定忽略的字段。** @param sourceJsonStr  原始JSON字符串* @param targetJsonStr 当前JSON字符串* @param ignoreFields   忽略的字段列表* @return 包含差异的Map*/public static Map<String, Map<String, String>> getDiffMap(String sourceJsonStr, String targetJsonStr, List<String> ignoreFields) {try {JsonObject sourceJson = new JsonParser().parse(sourceJsonStr).getAsJsonObject();JsonObject targetJson = new JsonParser().parse(targetJsonStr).getAsJsonObject();Map<String, String> sourceMap = new LinkedHashMap<>();Map<String, String> targetMap = new LinkedHashMap<>();convertJsonToMap(sourceJson, StringUtils.EMPTY, sourceMap, ignoreFields);convertJsonToMap(targetJson, StringUtils.EMPTY, targetMap, ignoreFields);return doCompare(sourceMap, targetMap);} catch (JsonSyntaxException e) {log.error("Failed to parse JSON string", e);return new HashMap<>();}}/*** 将JSON对象转换为Map,忽略指定的字段。** @param json         JSON对象* @param root         当前JSON路径* @param resultMap    存储转换结果的Map* @param ignoreFields 忽略的字段列表*//*** 将JSON对象转换为Map,忽略指定的字段。** @param json         JSON对象* @param root         当前JSON路径* @param resultMap    存储转换结果的Map* @param ignoreFields 忽略的字段列表*/private static void convertJsonToMap(JsonElement json, String root, Map<String, String> resultMap, List<String> ignoreFields) {if (json.isJsonObject()) {JsonObject jsonObject = json.getAsJsonObject();for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {String key = entry.getKey();if (CollectionUtils.isNotEmpty(ignoreFields) && ignoreFields.contains(key)) {continue;}JsonElement value = entry.getValue();String newRoot = (root.isEmpty())? key : root + DOT_SEPARATOR + key;if (value.isJsonObject() || value.isJsonArray()) {convertJsonToMap(value, newRoot, resultMap, ignoreFields);} else if(value.isJsonPrimitive()){resultMap.put(newRoot, value.getAsJsonPrimitive().getAsString());}}} else if (json.isJsonArray()) {JsonArray jsonArray = json.getAsJsonArray();for (int i = 0; i < jsonArray.size(); i++) {JsonElement value = jsonArray.get(i);String newRoot = (root.isEmpty())? "[" + i + "]" : root + "[" + i + "]";if (value.isJsonObject() || value.isJsonArray()) {convertJsonToMap(value, newRoot, resultMap, ignoreFields);} else if(value.isJsonPrimitive()){resultMap.put(newRoot, value.getAsJsonPrimitive().getAsString());}}}}/*** 执行实际的比较操作,返回包含差异的Map** @param sourceMap  原始Map* @param targetMap 当前Map* @return 包含差异的Map*/private static Map<String, Map<String, String>> doCompare(Map<String, String> sourceMap, Map<String, String> targetMap) {Map<String, Map<String, String>> diffMap = new HashMap<>();for (Map.Entry<String, String> entry : targetMap.entrySet()) {String key = entry.getKey();String newValue = entry.getValue();String oldValue = sourceMap.get(key);if (sourceMap.containsKey(key)) {if (!ObjectUtils.equals(newValue, oldValue)) {addDiffMap(diffMap, key, oldValue, newValue);}} else {addDiffMap(diffMap, key, StringUtils.EMPTY, newValue);}}return diffMap;}/*** 将差异项添加到差异映射中。** 此方法用于在处理两个数据集的差异时,将特定的差异项添加到一个映射中,* 其中每个差异项由一个键值对表示,包括源值和目标值。** @param diffMap 保存差异项的映射,其中键是差异项的标识,值是包含源值和目标值的映射。* @param key 差异项的标识,用于在diffMap中作为键。* @param value 源对象中的值,表示差异的起始点。* @param targetValue 目标对象中的值,表示与源值不同的目标值。*/private static void addDiffMap(Map<String, Map<String, String>> diffMap, String key, String value, String targetValue) {Map<String, String> diffItemMap = new HashMap<>();diffItemMap.put(SOURCE_VALUE, value);diffItemMap.put(TARGET_VALUE, targetValue);diffMap.put(key, diffItemMap);}
}
测试:
public class 对象字段差异 {public static void main(String[] args) {User user = new User();user.setName("夏天");user.setAge(18);user.setPhone("苹果");user.setPhoneNumber("177");List<String> ignoreFields = Collections.singletonList("address");User user1 = new User();user1.setName("夏天");user1.setAge(188);user1.setPhone("华为");user1.setPhoneNumber("177");Map<String, Map<String, String>> diffMap = ModelDiffUtil.getDiffMap(user, user1, ignoreFields);System.out.println(diffMap);Map<String, String> map = AnnotationUtil.printFieldLabels(User.class);System.out.println(map);System.out.println("--------------------------");List<String> diff = new java.util.ArrayList<>(Collections.emptyList());diffMap.forEach((k, v) -> {String object = map.get(k);if (StrUtil.isNotBlank(object)) {diff.add(object);}});System.out.println(diff);}
}
结果:

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

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

相关文章

OpenEBS 实现 PV 动态持久化存储安装

什么是 OpenEBS OpenEBS 将 Kubernetes 工作节点可用的任何存储转换为本地或复制的 Kubernetes 持久卷。OpenEBS 可帮助应用程序和平台团队轻松部署需要快速、高持久性、可靠且可扩展的容器原生存储的Kubernetes 有状态工作负载。 安装OpenEBS 1.所有节点安装iSCSI启动器 yu…

PostgreSQL学习笔记四:GUI管理工具

PostgreSQL 是一款广泛使用的开源关系数据库管理系统&#xff0c;拥有许多图形用户界面&#xff08;GUI&#xff09;工具来帮助用户更高效地管理数据库。以下是一些流行的 PostgreSQL 管理工具&#xff1a; pgAdmin&#xff1a; 一个流行的开源 PostgreSQL GUI 工具&#xff0c…

Graph知识图谱融入向量数据库,带来RAG效果飞升

01. 前言 随着大型语言模型&#xff08;LLMs&#xff09;在各种应用中的广泛使用&#xff0c;如何提升其回答的准确性和相关性成为一个关键问题。检索增强生成&#xff08;RAG&#xff09;技术通过整合外部知识库&#xff0c;为LLMs提供了额外的背景信息&#xff0c;有效地改…

Linux-sed和gawk

文本处理-sed编辑器 文本处理-gawk程序 文本处理-sed编辑器基础 文本处理-sed编辑器基础-使用地址 文本处理-sed编辑器基础-删除行 文本处理-sed编辑器基础-插入和附加文本 文本处理-sed编辑器基础-修改行/转换命令 文本处理-sed编辑器基础-回顾打印-打印行/打印行号/列出行 文…

「OC」NSArray的底层逻辑和遍历方法

「OC」NSArray的底层逻辑和遍历方法 文章目录 「OC」NSArray的底层逻辑和遍历方法前言NSArray的底层逻辑占位符init后的空NSArray只有单个元素的NSArray大于一个元素的NSArray可变数组NSMutableArray总结图片 遍历NSArray1. for循环2. 枚举3.for—in4. 多线程1.for 循环&fo…

MES管理系统对中小企业有哪些帮助

MES管理系统解决方案对中小企业具有显著的帮助&#xff0c;主要体现在以下几个方面&#xff1a; 一、提升生产效率 MES管理系统能够实时监控生产过程&#xff0c;提供准确的生产数据和及时的反馈。这种实时监控与数据分析能力&#xff0c;使中小企业能够精准把握生产脉搏&…

华为---MUX VLAN简介及示例配置

目录 1. 产生背景 2. 应用场景 3. 主要功能 4. 基本概念 5. 配置步骤及相关命令 6.示例配置 6.1 示例场景 6.2 网络拓扑图 6.3 配置代码 6.4 配置及解析 6.5 测试验证 配置注意事项 1. 产生背景 MUX VLAN&#xff08;Multiplex VLAN&#xff09;提供了一种通过VLA…

【JavaScript】JavaScript 与 V8

浏览器中运行 html 和 css 代码&#xff1a; html 和 css 执行过程&#xff1a; js 由 js 引擎&#xff08;比如现在最为主流的 V8&#xff09;执行。 高级的编程语言都是需要转成最终的机器指令来执行的&#xff1b;事实上我们编写的JavaScript无论你交给浏览器或者Node执行&…

升级 OpenSSL 的详细步骤(解决 SSH 漏洞的前提)

目录 前言1. 准备工作1.1 安装必要的依赖1.2 下载 OpenSSL 源码 2. 解压和配置2.1 解压文件2.2 配置编译参数 3. 编译和安装3.1 编译源码3.2 安装 OpenSSL 4. 验证安装5. 解决 SSH 漏洞的必要性6. 结语 前言 在信息安全的时代&#xff0c;服务器的安全性至关重要。特别是在互联…

高被引算法GOA优化VMD,结合Transformer-SVM的轴承诊断,保姆级教程!

本期采用2023年瞪羚优化算法优化VMD&#xff0c;并结合Transformer-SVM实现轴承诊断&#xff0c;算是一个小创新方法了。需要水论文的童鞋尽快&#xff01; 瞪羚优化算法之前推荐过&#xff0c;该成果于2023年发表在计算机领域三区SCI期刊“Neural Computing and Applications”…

智能配音软件哪款好?分享5个搞怪软件

想要让视频或社交媒体内容更加生动有趣&#xff1f;搞笑配音软件是个不错的选择。 无论是嘻哈风格的视频&#xff0c;还是搞怪的段子&#xff0c;合适的配音都能让内容增色不少。 今天&#xff0c;就让我们来探索六个文字配音软件&#xff0c;它们不仅能帮你实现搞笑配音&…

Centos7安装RocketMQ[图文教程]

文章目录 RocketMQ介绍基于Linux服务部署RocketMQ&#xff08;单机&#xff09;配置JDK环境下载RocketMQ部署RocketMQ1、解压2、修改VM参数3、配置环境变量4、编写Service文件5、启动服务 基于Docker方式部署RocketMQ安装Docker编写docker-compose文件启动RocketMQ服务 部署Roc…

嵌入式面试——FreeRTOS篇(四) 信号量

本篇为&#xff1a;FreeRTOS信号量篇 信号量 1、什么是信号量 答&#xff1a; 信号量是一种解决同步问题的机制&#xff0c;可以实现对共享资源的有序访问。 2、信号量简介 答&#xff1a; 当计数值大于0&#xff0c;表示有信号量资源。当释放信号量&#xff0c;信号量计数…

SQL 干货 | 使用 EXISTS 编写 SELECT 查询

基于 SQL 中的 EXISTS 运算符为我们提供了一种基于其他数据是否存在&#xff08;或不存在&#xff09;来检索数据的简便方法。更具体地说&#xff0c;它是一个逻辑运算符&#xff0c;用于评估子查询的结果&#xff0c;并返回一个布尔值&#xff0c;该值指示是否返回了行。尽管 …

Elasticsearch 实战应用

Elasticsearch 实战应用 引言 Elasticsearch 是一个分布式、RESTful 风格的搜索和分析引擎&#xff0c;能够快速、实时地处理大规模数据&#xff0c;广泛应用于全文搜索、日志分析、推荐系统等领域。在这篇博客中&#xff0c;我们将从 Elasticsearch 的基本概念入手&#xff…

ubuntu 开放 8080 端口快捷命令

文章目录 查看防火墙状态开放 80 端口开放 8080 端口开放 22端口开启防火墙重启防火墙**使用 xhell登录**&#xff1a; 查看防火墙状态 sudo ufw status [sudo] password for crf: Status: inactivesudo ufw enable Firewall is active and enabled on system startup sudo…

curl执行报【先没有那个文件或目录】解决办法

开发微信发过了curl命令后&#xff0c;执行报错 是空格导致的&#xff0c;解决办法是打开下面网址重新输入空格即可 在线curl命令转代码 删除这个空格 重新输入空格

SCI论文快速排版:word模板一键复制样式和格式【重制版】

关注B站可以观看更多实战教学视频&#xff1a;hallo128的个人空间 SCI论文快速排版&#xff1a;word模板一键复制样式和格式&#xff1a;视频操作 SCI论文快速排版&#xff1a;word模板一键复制样式和格式【重制版】 模板与普通文档的区别 为了让读者更好地了解模板&#xff…

国产工具链GCKontrol-GCAir助力控制律开发快速验证

前言 随着航空领域技术的不断发展&#xff0c;飞机的飞行品质评估和优化成为了航空领域的一个重要任务&#xff0c;为了确保飞行器在各种复杂条件下的稳定性&#xff0c;控制律设计过程中的模型和数据验证需要大量仿真和测试。 本文将探讨基于世冠科技的国产软件工具链GCKont…

前端Vue3字体优化三部曲(webFont、font-spider、spa-font-spider-webpack-plugin)

前端Vue字体优化三部曲&#xff08;webFont、font-spider、spa-font-spider-webpack-plugin&#xff09; 引言 最近前端引入了UI给的思源黑体字体文件&#xff0c;但是字体文件过于庞大&#xff0c;会降低页面首次加载的速度&#xff0c;目前我的项目中需要用到如下三个字体文…