通过反射机制,比较两个对象的字段值的差异

开发需求中会存在比较前端传来的数据与后台数据有哪些数据发生了改变,一个一个字段比较太麻烦了,通过以下方法可以便捷的比较出来

java 复制代码
//实现方法
 private static List<ChangeContentDTO> getDifferentField(Object obj, Object afterObj) {
        try {
            //首先,创建一个空的列表用于存储变化的内容。
            List<ChangeContentDTO> changeContentDTOList = new ArrayList<>();
            //检查传入的两个对象是否为空,如果任何一个对象为空,则直接返回空列表。
            if (Objects.isNull(obj) || Objects.isNull(afterObj)) {
                return changeContentDTOList ;
            }
            // 获取对象的 Class 对象,然后获取这个 Class 对象的所有字段。
            Class<?> clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                // 遍历这些字段,对于每一个字段,首先设置它可以被访问(因为默认情况下,Java 的私有字段是不能被直接访问的)。
                field.setAccessible(true);
                if (Objects.isNull(field.get(obj))) {
                    continue;
                }
                DefinedAnnotation annotation= field.getDeclaredAnnotation(DefinedAnnotation.class);
                //检查字段的值是否为空,如果为空,则跳过这个字段。
                if (Objects.nonNull(annotation)&&!Objects.equals(field.get(obj), field.get(afterObj))) {
                    //获取字段的注解,如果字段有定义的注解,并且字段的值在两个对象中不同,则创建一个 DTO 对象,将字段的名称、注解的名称、变化前的值和变化后的值存入 DTO 对象,然后将这个 DTO 对象添加到列表中。
                    ChangeContentDTO dto = ChangeContentDTO.builder()
                            .fieldCode(field.getName())
                            .fieldName(annotation.name())
                            .changeBefore(field.get(obj))
                            .changeAfter(field.get(afterObj)).build();
                    changeContentDTOList.add(dto);
                }
            }
            return changeContentDTOList;
        } catch (IllegalAccessException e) {
            throw new BusinessException(BasicErrorCode.BIZ_ERROR, "通过反射获取对象字段的值失败");
        }

    }
java 复制代码
//创建bean对象存储变化的数据
@ApiModel("变更内容DTO")
@Getter
@Setter
@Builder
public class ChangeContentDTO {

    @ApiModelProperty("字段名称")
    private String fieldCode;

    @ApiModelProperty("字段名称")
    private String fieldName;

    @ApiModelProperty("变更前的内容")
    private Object changeBefore;

    @ApiModelProperty("变更后的内容")
    private Object changeAfter;

}
java 复制代码
//main方法测试
 public static void main(String[] args) {
        ResourceEntity resourceEntity = new ResourceEntity();
        ResourceEntity resourceEntity1 = new ResourceEntity();
        resourceEntity.setCode("111");
        resourceEntity1.setCode("222");
        resourceEntity.setName("name");
        resourceEntity1.seName("name");
        List<ChangeContentDTO> list = getDifferentField(resourceEntity, resourceEntity1);
        System.out.println(list);
    }
相关推荐
小北方城市网4 小时前
Redis 分布式锁高可用实现:从原理到生产级落地
java·前端·javascript·spring boot·redis·分布式·wpf
六义义5 小时前
java基础十二
java·数据结构·算法
毕设源码-钟学长6 小时前
【开题答辩全过程】以 基于SpringBoot的智能书城推荐系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
笨手笨脚の6 小时前
深入理解 Java 虚拟机-03 垃圾收集
java·jvm·垃圾回收·标记清除·标记复制·标记整理
莫问前路漫漫6 小时前
WinMerge v2.16.41 中文绿色版深度解析:文件对比与合并的全能工具
java·开发语言·python·jdk·ai编程
九皇叔叔6 小时前
【03】SpringBoot3 MybatisPlus BaseMapper 源码分析
java·开发语言·mybatis·mybatis plus
挖矿大亨6 小时前
c++中的函数模版
java·c++·算法
a程序小傲7 小时前
得物Java面试被问:RocketMQ的消息轨迹追踪实现
java·linux·spring·面试·职场和发展·rocketmq·java-rocketmq
青春男大7 小时前
Redis和RedisTemplate快速上手
java·数据库·redis·后端·spring·缓存
Ghost Face...7 小时前
i386 CPU页式存储管理深度解析
java·linux·服务器