事件回顧
分析探討
推薦方案
總結(jié)
前言
最近項(xiàng)目上要求升級(jí)一個(gè)工具包hutool的版本,以解決安全漏洞問(wèn)題,這不升級(jí)還好,一升級(jí)反而捅出了更大的簍子,究竟是怎么回事呢?
基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶(hù)小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶(hù)、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
項(xiàng)目地址:https://github.com/YunaiV/ruoyi-vue-pro
視頻教程:https://doc.iocoder.cn/video/
事件回顧
我們項(xiàng)目原先使用的hutool版本是5.7.2,在代碼中,我們的數(shù)據(jù)傳輸對(duì)象DTO和數(shù)據(jù)實(shí)體對(duì)象中大量使用了工具包中的BeanUtil.copyProperties(), 大體代碼如下:
數(shù)據(jù)傳輸對(duì)象
@Data @ToString publicclassDiagramDTO{ //前端生產(chǎn)的字符串id privateStringid; privateStringcode; privateStringname; }
數(shù)據(jù)實(shí)體對(duì)象
@Data @ToString publicclassDiagram{ privateIntegerid; privateStringcode; privateStringname; }
業(yè)務(wù)邏輯
publicclassBeanCopyTest{ publicstaticvoidmain(String[]args){ //前端傳輸?shù)膶?duì)象 DiagramDTOdiagramDTO=newDiagramDTO(); //如果前端傳入的id事包含e的,升級(jí)后就會(huì)報(bào)錯(cuò) diagramDTO.setId("3em3dgqsgmn0"); diagramDTO.setCode("d1"); diagramDTO.setName("圖表"); Diagramdiagram=newDiagram(); //關(guān)鍵點(diǎn),數(shù)據(jù)拷貝 BeanUtil.copyProperties(diagramDTO,diagram); System.out.println("數(shù)據(jù)實(shí)體對(duì)象:"+diagram); //設(shè)置id為空,自增 diagram.setId(null); //保存到數(shù)據(jù)庫(kù)中TODO //diagramMapper.save(diagram); } }
升級(jí)前,hutool是5.7.2版本下,執(zhí)行結(jié)果如下圖。
BeanUtil.copyProperties雖然字段類(lèi)型不一樣,但是做了兼容處理,所以業(yè)務(wù)沒(méi)有影響業(yè)務(wù)邏輯。
升級(jí)后,hutool是5.8.8版本,執(zhí)行結(jié)果如下圖所示:
執(zhí)行報(bào)錯(cuò),因?yàn)樯?jí)后的版本修改了實(shí)現(xiàn),增加了下面的邏輯,如果包含E, 就會(huì)拋錯(cuò),從而影響了業(yè)務(wù)邏輯,同時(shí)這個(gè)id是否包含e又是隨機(jī)因素,到了生產(chǎn)才發(fā)現(xiàn),就悲劇了。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶(hù)小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶(hù)、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
項(xiàng)目地址:https://github.com/YunaiV/yudao-cloud
視頻教程:https://doc.iocoder.cn/video/
分析探討
我發(fā)現(xiàn)大部分人寫(xiě)代碼都喜歡偷懶,在上面的場(chǎng)景中,雖然BeanUtil.copyProperties用的一時(shí)爽,但有時(shí)候帶來(lái)的后果是很?chē)?yán)重的,所以很不推薦這種方式。為什么這么說(shuō)呢?
比如團(tuán)隊(duì)中的某些人偷偷改了數(shù)據(jù)傳輸對(duì)象DTO,比如修改了類(lèi)型、刪去了某個(gè)字段。用BeanUtil.copyProperties的方式壓根無(wú)法在編譯階段發(fā)現(xiàn),更別提修改的影響范圍了,這就只能把風(fēng)險(xiǎn)暴露到生產(chǎn)上去了。那有什么更好的方法呢?
推薦方案
原始的get、set方式
我是比較推崇這種做法的,比如現(xiàn)在DiagramDTO刪去某個(gè)字段,編譯器就會(huì)報(bào)錯(cuò),就會(huì)引起你的注意了,讓問(wèn)題提前暴露,無(wú)處遁形。
你可能覺(jué)得站著說(shuō)話(huà)不腰疼,字段少好,如果字段很多還不得寫(xiě)死啊,我這里推薦一個(gè)IDEA的插件,可以幫你智能生成這樣的代碼。
話(huà)不多說(shuō),自己玩兒去~~
使用開(kāi)源庫(kù)ModelMapper
ModelMapper是一個(gè)開(kāi)源庫(kù),可以很方便、簡(jiǎn)單地將對(duì)象從一種類(lèi)型映射到另一種類(lèi)型,底層是通過(guò)反射來(lái)自動(dòng)確定對(duì)象之間的映射,還可以自定義映射規(guī)則。
privatestaticvoidtestModelMapper(){ ModelMappermodelMapper=newModelMapper(); DiagramDTOdiagramDTO=newDiagramDTO(); diagramDTO.setId("3em3dgqsgmn0"); diagramDTO.setCode("d1"); diagramDTO.setName("圖表"); Diagramdiagram=modelMapper.map(diagramDTO,Diagram.class); }
使用開(kāi)源庫(kù)MapStruct
MapStruct也是Java中另外一個(gè)用于映射對(duì)象很流行的開(kāi)源工具。它是在編譯階段生成對(duì)應(yīng)的映射代碼,相對(duì)于ModelMapper底層放射的方案,性能更好。
@Mapper publicinterfaceDiagramMapper{ DiagramMapperINSTANCE=Mappers.getMapper(DiagramMapper.class); DiagramDTOtoDTO(Diagramdiagram); DiagramtoEntity(DiagramDTOdiagram); } privatestaticvoidtestMapStruct(){ DiagramDTOdiagramDTO=newDiagramDTO(); diagramDTO.setId("3em3dgqsgmn0"); diagramDTO.setCode("d1"); diagramDTO.setName("圖表"); Diagramdiagram=DiagramMapper.INSTANCE.toEntity(diagramDTO); }
DiagramMapper接口使用了@Mapper注解,用來(lái)表明使用MapStruct處理
MapStruct中更多高級(jí)特性大家自己探索一下。
總結(jié)
小結(jié)一下,對(duì)象在不同層之間進(jìn)行轉(zhuǎn)換映射,很不建議使用BeanUtil.copyProperties這種方式,更加推薦使用原生的set, get方式,不容易出錯(cuò)。當(dāng)然這不是將BeanUtil.copyProperties一棒子打死,毫無(wú)用武之地,在特定場(chǎng)景,比如方法內(nèi)部對(duì)象的轉(zhuǎn)換等影響小的范圍還是很方便的。
-
代碼
+關(guān)注
關(guān)注
30文章
4894瀏覽量
70449 -
編譯
+關(guān)注
關(guān)注
0文章
676瀏覽量
33873
原文標(biāo)題:麻了!不要再動(dòng)不動(dòng)就用BeanUtil.copyProperties了!!
文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
Python高級(jí)特性:迭代器切片的應(yīng)用
對(duì)象轉(zhuǎn)換工具:MapStruct 庫(kù)
LabVIEW中調(diào)用DLL的高級(jí)技巧后續(xù)資源包
Trace32的高級(jí)功能特性

在設(shè)計(jì)中如何使用高級(jí)PCB模塊
STMCube.AI的高級(jí)特性

STM32Cube.AI庫(kù)的高級(jí)特性

SOK將HugeCTR中的高級(jí)特性進(jìn)行包裝使用

英特爾高級(jí)鏈路分析器全新混合行為模式,兼“雙優(yōu)”特性
別再用BeanUtils了,這款PO VO DTO轉(zhuǎn)換神器不香么?

評(píng)論