麻了,不要再动不动就BeanUtil.copyProperties!!!
2023/4/16 14:22:24
本文主要是介绍麻了,不要再动不动就BeanUtil.copyProperties!!!,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
最近项目上要求升级一个工具包hutool
的版本,以解决安全漏洞问题,这不升级还好,一升级反而捅出了更大的篓子,究竟是怎么回事呢?
事件回顾
我们项目原先使用的hutool
版本是5.7.2,在代码中,我们的数据传输对象DTO和数据实体对象中大量使用了工具包中的BeanUtil.copyProperties()
, 大体代码如下:
- 数据传输对象
@Data @ToString public class DiagramDTO { // 前端生产的字符串id private String id; private String code; private String name; }
- 数据实体对象
@Data @ToString public class Diagram { private Integer id; private String code; private String name; }
- 业务逻辑
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
的方式压根无法在编译阶段发现,更别提修改的影响范围了,这就只能把风险暴露到生产上去了。那有什么更好的方法呢?
推荐方案
- 原始的
get
、set
方式
我是比较推崇这种做法的,比如现在DiagramDTO
删去某个字段,编译器就会报错,就会引起你的注意了,让问题提前暴露,无处遁形。
你可能觉得站着说话不腰疼,字段少好,如果字段很多还不得写死啊,我这里推荐一个IDEA的插件,可以帮你智能生成这样的代码。
话不多说,自己玩儿去~~
- 使用开源库
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); }
- 使用开源库
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!!!的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-10Rakuten 乐天积分系统从 Cassandra 到 TiDB 的选型与实战
- 2025-01-09CMS内容管理系统是什么?如何选择适合你的平台?
- 2025-01-08CCPM如何缩短项目周期并降低风险?
- 2025-01-08Omnivore 替代品 Readeck 安装与使用教程
- 2025-01-07Cursor 收费太贵?3分钟教你接入超低价 DeepSeek-V3,代码质量逼近 Claude 3.5
- 2025-01-06PingCAP 连续两年入选 Gartner 云数据库管理系统魔力象限“荣誉提及”
- 2025-01-05Easysearch 可搜索快照功能,看这篇就够了
- 2025-01-04BOT+EPC模式在基础设施项目中的应用与优势
- 2025-01-03用LangChain构建会检索和搜索的智能聊天机器人指南
- 2025-01-03图像文字理解,OCR、大模型还是多模态模型?PalliGema2在QLoRA技术上的微调与应用