前言

最近项目上要求升级一个工具包hutool的版本,以解决安全漏洞问题,这不升级还好,一升级反而捅出了更大的篓子,究竟是怎么回事呢?

事件回顾

我们项目原先使用的hutool版本是5.7.2,在代码中,我们的数据传输对象DTO和数据实体对象中大量使用了工具包中的BeanUtil.copyProperties(), 大体代码如下:

  1. 数据传输对象
@Data
@ToString
public class DiagramDTO { // 前端生产的字符串id
private String id; private String code; private String name;
}
  1. 数据实体对象
@Data
@ToString
public class Diagram { private Integer id; private String code; private String name;
}
  1. 业务逻辑
public class BeanCopyTest {

    public static void main(String[] args) {
// 前端传输的对象
DiagramDTO diagramDTO = new DiagramDTO();
// 如果前端传入的id事包含e的,升级后就会报错
diagramDTO.setId("3em3dgqsgmn0");
diagramDTO.setCode("d1");
diagramDTO.setName("图表"); Diagram diagram = new Diagram();
// 关键点,数据拷贝
BeanUtil.copyProperties(diagramDTO, diagram);
System.out.println("数据实体对象:" + diagram);
//设置id为空,自增
diagram.setId(null);
//保存到数据库中 TODO
//diagramMapper.save(diagram);
}
}

升级前,hutool是5.7.2版本下,执行结果如下图。

  • BeanUtil.copyProperties虽然字段类型不一样,但是做了兼容处理,所以业务没有影响业务逻辑。

升级后,hutool是5.8.8版本,执行结果如下图所示:

  • 执行报错,因为升级后的版本修改了实现,增加了下面的逻辑,如果包含E, 就会抛错,从而影响了业务逻辑,同时这个id是否包含e又是随机因素,到了生产才发现,就悲剧了。

分析探讨

我发现大部分人写代码都喜欢偷懒,在上面的场景中,虽然BeanUtil.copyProperties用的一时爽,但有时候带来的后果是很严重的,所以很不推荐这种方式。为什么这么说呢?

比如团队中的某些人偷偷改了数据传输对象DTO,比如修改了类型、删去了某个字段。用BeanUtil.copyProperties的方式压根无法在编译阶段发现,更别提修改的影响范围了,这就只能把风险暴露到生产上去了。那有什么更好的方法呢?

推荐方案

  1. 原始的getset方式

我是比较推崇这种做法的,比如现在DiagramDTO删去某个字段,编译器就会报错,就会引起你的注意了,让问题提前暴露,无处遁形。

你可能觉得站着说话不腰疼,字段少好,如果字段很多还不得写死啊,我这里推荐一个IDEA的插件,可以帮你智能生成这样的代码。

话不多说,自己玩儿去~~

  1. 使用开源库ModelMapper

ModelMapper是一个开源库,可以很方便、简单地将对象从一种类型映射到另一种类型,底层是通过反射来自动确定对象之间的映射,还可以自定义映射规则。

 private static void testModelMapper() {
ModelMapper modelMapper = new ModelMapper();
DiagramDTO diagramDTO = new DiagramDTO();
diagramDTO.setId("3em3dgqsgmn0");
diagramDTO.setCode("d1");
diagramDTO.setName("图表");
Diagram diagram = modelMapper.map(diagramDTO, Diagram.class);
}
  1. 使用开源库MapStruct

MapStruct也是Java中另外一个用于映射对象很流行的开源工具。它是在编译阶段生成对应的映射代码,相对于ModelMapper底层放射的方案,性能更好。

@Mapper
public interface DiagramMapper {
DiagramMapper INSTANCE = Mappers.getMapper(DiagramMapper.class); DiagramDTO toDTO(Diagram diagram); Diagram toEntity(DiagramDTO diagram);
} private static void testMapStruct() {
DiagramDTO diagramDTO = new DiagramDTO();
diagramDTO.setId("3em3dgqsgmn0");
diagramDTO.setCode("d1");
diagramDTO.setName("图表");
Diagram diagram = DiagramMapper.INSTANCE.toEntity(diagramDTO);
}
  • DiagramMapper接口使用了@Mapper注解,用来表明使用MapStruct处理
  • MapStruct中更多高级特性大家自己探索一下。

总结

小结一下,对象在不同层之间进行转换映射,很不建议使用BeanUtil.copyProperties这种方式,更加推荐使用原生的set, get方式,不容易出错。当然这不是将BeanUtil.copyProperties一棒子打死,毫无用武之地,在特定场景,比如方法内部对象的转换等影响小的范围还是很方便的,如果你有其他的想法,也可以留下你的想法,一起探讨交流。

欢迎关注个人公众号【JAVA旭阳】交流学习!!

麻了,不要再动不动就BeanUtil.copyProperties!!!的更多相关文章

  1. 12种 vo2dto 方法,就 BeanUtils.copyProperties 压测最拉胯!【快双11了,别用错喽】

    作者:小傅哥 博客:https://bugstack.cn 原文:https://mp.weixin.qq.com/s/Xq7oQg7dYESMYxHVnxX8Dw 沉淀.分享.成长,让自己和他人都能 ...

  2. 推荐几个牛逼的 IDEA 插件,还带动图!

    阅读本文大概需要 2.3 分钟. 作者:纪莫, cnblogs.com/jimoer 这里只是推荐一下好用的插件,具体的使用方法不一一详细介绍. JRebel for IntelliJ 一款热部署插件 ...

  3. IDEA 破解_补丁永久_2018.3

           主要是Eclipse我已经玩坏了三次了,切换jdk8到jdk10,再切换到jdk8,大量文件乱码,怎么改都没用,有的时候Eclipse久了不用,项目放在里面发霉了,坏掉了,MMP,换到I ...

  4. 推荐几个IDEA插件,Java开发者撸码利器(转载)

    推荐几个IDEA插件,Java开发者撸码利器.   这里只是推荐一下好用的插件,具体的使用方法不一一详细介绍. JRebel for IntelliJ 一款热部署插件,只要不是修改了项目的配置文件,用 ...

  5. IDEA Java开发常用插件

    这里只是推荐一下好用的插件,具体的使用方法就不一一详细介绍了. JRebel for IntelliJ 一款热部署插件,只要不是修改了项目的配置文件,用它都可以实现热部署.收费的,破解比较麻烦.不过功 ...

  6. IDEA常用插件记录

    让我们来记录一下常用的IDEA插件:(从其他博客中取了许多图片,出处见图片水印) 1.JRebel for IntelliJ 热部署神器2.Free MyBatis plugin 实现dao层方法与x ...

  7. 利用双重检查锁定和CAS算法:解决并发下数据库的一致性问题

    背景 ​ 最近有一个场景遇到了数据库的并发问题.现在先由我来抽象一下,去掉不必要的繁杂业务. ​ 数据库表book存储着每本书的阅读量,一开始数据库是空的,不存在任何的数据.当用户访问接口的时候,判断 ...

  8. IntelliJ IDEA 插件推荐

    1.GenerateAllSetter 自动生成类set方法 2.GsonFormat 根据JSON创建实体 3.Lombok plugin 简化代码 4. .ignore 忽略git提交文件 5.A ...

  9. 用 Java 实现人脸识别功能(附源码)

    整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 更多优选 一口气说出 9种 分布式ID生成方式,面试官有点懵了 ...

  10. 推荐 10个 NB的 IDEA 插件,开发效率至少提升一倍

    友情提示:插件虽好,可不要贪装哦,装多了会 卡 .卡 .卡 ~ 正经干活用的 分享一点自己工作中得心应手的IDEA插件,可不是在插件商店随随便便搜的,都经过实战检验,用过的都说好.可能有一些大家用过的 ...

随机推荐

  1. django orm的增删改查 以及django1.x和2.x的区别

    ORM对字段的增删改查 # 建一个作者表 class Author(models.Model): ''' 如果你以后在创建表的时候,主键就叫id名,那么可以省略不写,orm会自动帮你创建出主键名称为i ...

  2. Laravel安装第一步:Windows 10 上laravel下载与安装需要注意。

    1.下载了laravel,查看composer.json文件,搞清楚它需要的PHP版本 2.不要用 composer install !!! 用  composer -vvv install   这样 ...

  3. 介绍String、StringBuffer和StringBuilder

    1. String类:  位于java.lang包,早期版本JDK1.0,继承Object类,实现java.io.Serializable, Comparable<String>, Cha ...

  4. 转载:VMware Esxi开通SSH功能

    转载:https://www.cnblogs.com/dsl146/p/13739953.html ESXi 5.5是直接安装在物理主机上的一个虚拟机系统,本质上是一个Linux系统.平时可以通过VM ...

  5. Linux挂载U盘报错:mount: unknown filesystem type 'ntfs'

    原因:由于Linux上无法识别NTFS格式的分区的原因 解决方法:安装 ntfs-3g 1.下载:wget https://tuxera.com/opensource/ntfs-3g_ntfsprog ...

  6. Jmeter读取Csv文件,字段中有逗号分隔,读取不成功

    Jmeter读取Csv文件,字段中有逗号分隔,读取不成功

  7. Leecode 160.相交链表(Java 哈希表、双指针 两种方法)

    找两个链表第一次指针相同的地方     想法:(本来是没有的,因为没读懂题目描述= =) 1.两个指针,长的先走(长减短相差的长度)这么多的步数,然后就可以开始比较指针,直到指向为空,期间如果指针相同 ...

  8. 2021.06.29 mac系统下zsh: command not found:***报错问题

    最近老是遇到zsh: command not found:vue,zsh: command not found:nrm, zsh: command not found:tsc, zsh: comman ...

  9. PHP精度计算函数

    bcadd - 将两个高精度数字相加 bccomp - 比较两个高精度数字,返回-1, 0, 1 bcdiv - 将两个高精度数字相除 bcmod - 求高精度数字余数 bcmul - 将两个高精度数 ...

  10. 红米k40稳定版本刷开发版开启DC调光记录

    刷个开发版还要申请资格.要么去淘宝买资格的账号,要么用其他方法: 包21.4.15,直接有有防闪烁功能下载地址:https://bigota.d.miui.com/21.4.15/miui_ALIOT ...