彻底干掉 BeanUtils,最优雅的 Mapstruct 增强工具全新出炉(增强插件在哪)

  本篇文章为你整理了彻底干掉 BeanUtils,最优雅的 Mapstruct 增强工具全新出炉(增强插件在哪)的详细内容,包含有map增强for 增强插件在哪 彻底干掉 BeanUtils,最优雅的 Mapstruct 增强工具全新出炉,希望能帮助你了解 彻底干掉 BeanUtils,最优雅的 Mapstruct 增强工具全新出炉。

   全新出炉的 MapstructPlus 对 Mapstruct 做了全面升级,优化了其开发效率,增加了多种特性,该扔掉 BeanUtils 了!

  
在现在流行的系统设计中,一般会将对象模型划分为多个层次,例如 VO、DTO、PO、BO 等等。这同时也产生了一个问题,经常需要进行不同层级的模型之间相互转换。

  针对这种问题,目前常会采用三种方案:

  调用每个字段的 getter/setter 进行赋值。这个过程,枯燥且乏味,容易出错的同时,极易容易造成代码行数迅速膨胀,可阅读性差。

  apache-commons、Spring 等提供的 BeanUtil 工具类,这种工具类使用非常方便,一行代码即可实现映射。但其内部采用反射的方式来实现映射,性能低下,出现问题时,调试困难,当需要个性化转换时,配置麻烦,非常不建议使用,特别是对于性能要求比较高的程序中。

  mapstruct:这个框架是基于 Java 注释处理器,定义一个转换接口,在编译的时候,会根据接口类和方法相关的注解,自动生成转换实现类。生成的转换逻辑,是基于 getter/setter 方法的,所以不会像 BeanUtil 等消耗其性能。

  上面的三种方法中,最优秀的莫属 mapstruct 了,当然,美中不足的就是,当系统较为复杂,对象较多且结构复杂,又或者有的项目设计中会定义多层对象模型(如 DDD 领域设计),需要定义较多的转换接口和转换方法,这也是一些开发者放弃 Mapstruct 的主要原因。

  这里,就要给大家介绍一个 Mapstruct 的增强包 —— Mapstruct Plus,一个注解,可以生成两个类之间的转换接口,使 Java 类型转换更加便捷、优雅,彻底抛弃 BeanUtils。

  下面演示如何使用 MapStruct Plus 来映射两个对象。

  假设有两个类 UserDto 和 User,分别表示数据层对象和业务层对象:

  UserDto

  

public class UserDto {

 

   private String username;

   private int age;

   private boolean young;

   // getter、setter、toString、equals、hashCode

  

 

  

public class User {

 

   private String username;

   private int age;

   private boolean young;

   // getter、setter、toString、equals、hashCode

  

 

  引入 mapstruct-plus-spring-boot-starter 依赖:

  

 properties 

 

   mapstruct-plus.version 1.1.3 /mapstruct-plus.version

   /properties

   dependencies

   dependency

   groupId io.github.linpeilie /groupId

   artifactId mapstruct-plus-spring-boot-starter /artifactId

   version ${mapstruct-plus.version} /version

   /dependency

   /dependencies

   build

   plugins

   plugin

   groupId org.apache.maven.plugins /groupId

   artifactId maven-compiler-plugin /artifactId

   version 3.8.1 /version

   configuration

   source 1.8 /source

   target 1.8 /target

   annotationProcessorPaths

   path

   groupId io.github.linpeilie /groupId

   artifactId mapstruct-plus-processor /artifactId

   version ${mapstruct-plus.version} /version

   /path

   /annotationProcessorPaths

   /configuration

   /plugin

   /plugins

   /build

  

 

  指定对象映射关系

  在 User 或者 UserDto 上面增加注解 —— @AutoMapper,并设置 targetType 为对方类。

  例如:

  

@AutoMapper(target = UserDto.class)

 

  public class User {

   // ...

  

 

  

@SpringBootTest

 

  public class QuickStartTest {

   @Autowired

   private Converter converter;

   @Test

   public void test() {

   User user = new User();

   user.setUsername("jack");

   user.setAge(23);

   user.setYoung(false);

   UserDto userDto = converter.convert(user, UserDto.class);

   System.out.println(userDto); // UserDto{username=jack, age=23, young=false}

   assert user.getUsername().equals(userDto.getUsername());

   assert user.getAge() == userDto.getAge();

   assert user.isYoung() == userDto.isYoung();

   User newUser = converter.convert(userDto, User.class);

   System.out.println(newUser); // User{username=jack, age=23, young=false}

   assert user.getUsername().equals(newUser.getUsername());

   assert user.getAge() == newUser.getAge();

   assert user.isYoung() == newUser.isYoung();

  

 

  引入依赖后,使用 Mapstruct Plus 步骤非常简单。

  给需要转换的类添加 AutoMapper 注解

  获取 Converter 实例,调用 convert 方法即可

  完全兼容 Mapstruct

  Mapst实现了增强操作,如果之前已经使用了 Mapstruct,可以直接替换相关依赖。

  单注解即可实现两个对象相互转换

  例如快速开始中,只在 User 类上面增加注解 @AutoMapper,Mapstruct Plus 除了会生成 User - UserDto 的转换接口,默认还会生成 UserDto - User 的转换接口。

  编译后,可以查看生成的类,如下:

  自定义对象类型的属性自动转换

  当两个需要转换的对象 A 和 ADto,其中的属性 B 和 BDto 是自定义类型,并且也定义了 @AutoMapper 注解的话,在生成转换 A 和 ADto 时,会自动依赖属性 B 和 BDto 的转换接口,实现其相应的属性转换。

  例如:
 

  分别有两组对象模型:汽车(Car) 和座椅配置(SeatConfiguration),其中 Car 依赖 SeatConfiguration。

  两组对象结构一致,只不过代表层级不一样,这里拿 dto 层的对象定义举例:

  CarDto

  

@AutoMapper(target = Car.class)

 

  public class CarDto {

   private SeatConfigurationDto seatConfiguration;

  

 

  SeatConfiguration

  

@AutoMapper(target = SeatConfiguration.class)

 

  public class SeatConfigurationDto {

   private int seatCount;

  

 

  测试:

  

@Test

 

  public void carConvertTest() {

   CarDto carDto = new CarDto();

   SeatConfigurationDto seatConfigurationDto = new SeatConfigurationDto();

   seatConfigurationDto.setSeatCount(4);

   carDto.setSeatConfiguration(seatConfigurationDto);

   final Car car = converter.convert(carDto, Car.class);

   System.out.println(car); // Car(seatConfiguration=SeatConfiguration(seatCount=4))

   assert car.getSeatConfiguration() != null;

   assert car.getSeatConfiguration().getSeatCount() == 4;

  

 

  单个对象对多个对象进行转换

  Mapstruct Plus 提供了 @AutoMappers 注解,支持配置多个目标对象,进行转换。

  例如:有三个对象,User、UserDto、UserVO,User 分别要和其他两个对象进行转换。则可以按如下配置:

  

@Data

 

  @AutoMappers({

   @AutoMapper(target = UserDto.class),

   @AutoMapper(target = UserVO.class)

  public class User {

   // ...

  

 

  Map 转对象

  Mapstruct Plus 提供了 @AutoMapMapper 注解,支持生成 Map String, Object 转换为当前类的接口。同时,还支持 map 中嵌套 Map String, Object 转换为自定义类嵌套自定义类的场景。

  其中,map 中的 value 支持的类型如下:

  String

  BigDecimal

  BigInteger

  Integer

  Double

  Number

  Boolean

  LocalDateTime

  LocalDate

  LocalTime

  Calendar

  Currency

  自定义类(自定义类也需要增加 @AutoMapMapper 注解

  例如:

  有如下两个接口:

  MapModelA

  

@Data

 

  @AutoMapMapper

  public class MapModelA {

   private String str;

   private int i1;

   private Long l2;

   private MapModelB mapModelB;

  

 

  MapModelB

  

@Data

 

  @AutoMapMapper

  public class MapModelB {

   private Date date;

  

 

  测试:

  

@Test

 

  public void test() {

   Map String, Object mapModel1 = new HashMap ();

   mapModel1.put("str", "1jkf1ijkj3f");

   mapModel1.put("i1", 111);

   mapModel1.put("l2", 11231);

   Map String, Object mapModel2 = new HashMap ();

   mapModel2.put("date", DateUtil.parse("2023-02-23 01:03:23"));

   mapModel1.put("mapModelB", mapModel2);

   final MapModelA mapModelA = converter.convert(mapModel1, MapModelA.class);

   System.out.println(mapModelA); // MapModelA(str=1jkf1ijkj3f, i1=111, l2=11231, mapModelB=MapModelB(date=2023-02-23 01:03:23))

  

 

  支持自定义转换

  自定义属性转换

  Mapstruct Plus 提供了 @AutoMapping 注解,该注解在编译后,会变为 Mapstruct 中的 @Mapping 注解,已经实现了几个常用的注解属性。

  指定不同名称属性字段映射转换

  例如,Car 类中属性 wheels 属性,转换 CarDto 类型时,需要将该字段映射到 wheelList 上面,可以在 wheels 上面增加如下注解:

  

@AutoMapper(target = CarDto.class)

 

  public class Car {

   @AutoMapping(target = "wheelList")

   private List String wheels;

  

 

  自定义时间格式化

  在将 Date 类型的属性,转换为 String 类型时,可以通过 dateFormat 来指定时间格式化:

  

@AutoMapper(target = Goods.class)

 

  public class GoodsDto {

   @AutoMapping(target = "takeDownTime", dateFormat = "yyyy-MM-dd HH:mm:ss")

   private Date takeDownTime;

  

 

  自定义数字格式化

  当数字类型(double、long、BigDecimal)转换为 String 类型时,可以通过 numberFormat 指定 java.text.DecimalFormat 所支持的格式:

  

@AutoMapper(target = Goods.class)

 

  public class GoodsDto {

   @AutoMapping(target = "price", numberFormat = "$#.00")

   private int price;

  

 

  自定义 Java 表达式

  @AutoMapping 提供了 expression 属性,支持配置一段可执行的 Java 代码,来执行具体的转换逻辑。

  例如,当一个 List String 的属性,想要转换为用 , 分隔的字符串时,可以通过该配置,来执行转换逻辑:

  

@AutoMapper(target = UserDto.class)

 

  public class User {

   @AutoMapping(target = "educations", expression = "java(java.lang.String.join(",", source.getEducationList()))")

   private List String educationList;

  

 

  自定义类型转换器

  @AutoMapping 注解提供了 uses 属性,引入自定义的类型转换器,来提供给当前类转换时使用。

  实例场景:

  项目中会有字符串用,分隔,在一些类中,需要根据逗号拆分为字符串集合。针对于这种场景,可以有两种方式:首先可以指定字段映射时的表达式,但需要对每种该情况的字段,都添加表达式,复杂且容易出错。

  第二,就可以自定义一个类型转换器,通过uses来使用

  

public interface StringToListString {

 

   default List String stringToListString(String str) {

   return StrUtil.split(str);

  @AutoMapper(target = User.class, uses = StringToListStringConverter.class)

  public class UserDto {

   private String username;

   private int age;

   private boolean young;

   @AutoMapping(target = "educationList")

   private String educations;

   // ......

  

 

  测试:

  

 

 

  @SpringBootTest

  public class QuickStartTest {

   @Autowired

   private Converter converter;

   @Test

   public void ueseTest() {

   UserDto userDto = new UserDto();

   userDto.setEducations("1,2,3");

   final User user = converter.convert(userDto, User.class);

   System.out.println(user.getEducationList()); // [1, 2, 3]

   assert user.getEducationList().size() == 3;

  

 

  更多特性,可以查看官方文档

  Mapstruct Plus 相对于 Mapstruct 来说,继承了其高性能的特点,同时增强了其便携性和快速开发的特性,在系统模型设计较好(属性及类型基本一致)的情况下,开发成本极低,是时候和 BeanUtils 说再见了。

  以上就是彻底干掉 BeanUtils,最优雅的 Mapstruct 增强工具全新出炉(增强插件在哪)的详细内容,想要了解更多 彻底干掉 BeanUtils,最优雅的 Mapstruct 增强工具全新出炉的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: