しびれています。これ以上 BeanUtil.copyProperties を使用しないでください。! !

序文

最近、このプロジェクトでは、セキュリティの脆弱性の問題を解決するためにツールキットの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. 元のget方法set_

私はむしろこのアプローチを提唱しており、たとえば、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旭阳】交流学习!!

おすすめ

転載: juejin.im/post/7222305855978078265