您的位置 首页 java

还在纠结VO转换吗?试试MapStruct吧

背景:

在开发过程中,为了系统的分层,需要进行VO转换。大家手写各种get、set,代码量太大,而且容易出错。市面上有几种VO转换方式:利用反射、cjlib等等,有的有性能上的问题,有的对特殊的场景处理不是很好。

我们直接在编译阶段直接解析出来get、set,这样既解放了双手,又提高了性能。是不是很香?

MapStruct 应运而生。

MapStruct简介:

是一个Java注释处理器,用于生成类型安全的 bean 映射类。

您所要做的就是定义一个mapper接口,该接口声明任何所需的映射方法。在编译期间,Map struct 将生成此接口的实现。此实现使用普通的Java方法调用来在源对象和目标对象之间进行映射,即没有反射或类似。

与手工编写映射代码相比,MapStruct通过生成繁琐且易于编写的代码来节省时间。遵循约定优于配置方法。

与动态映射框架相比,MapStruct具有以下优势:

  • 通过使用普通方法调用而不是反射来快速执行。没有太多的性能损耗。
  • 编译时类型安全:只能映射相互映射的对象和属性,不会将实体意外映射到其他的 DTO 等。
  • 在构建时清除错误报告,如果映射不完整(并非所有目标属性都已映射);映射不正确(找不到合适的映射方法或类型转换)。构建阶段就能暴露转换错误,不会到运行阶段。

接入方式:

首先需要接入mapstruct,在 pom 中引入jar包。

         <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.4.2.Final</version>
        </dependency>  

加入 maven 插件中加入path

注意: maven-compiler-plugin版本一定要3.8.0以上;如果项目有用lombok,path还需要加入lombok-mapstruct-binding

 <plugin>
    <groupId>org. apache .maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <source>1.8</source> <!-- depending on your project -->
        <target>1.8</target> <!-- depending on your project -->
        < annotation ProcessorPaths>
            <path>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.16</version>
            </path>
            <path>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct-processor</artifactId>
                <version>1.4.2.Final</version>
            </path>
            <path>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok-mapstruct-binding</artifactId>
                <version>0.2.0</version>
            </path>
            <!-- other annotation processors -->
        </annotationProcessorPaths>
    </configuration>
</plugin>  

使用就非常简单了,只需要定义一个interface就可以了。

使用案例:

定义两个待转换的类:DemoDo,DemoDto

 package com.pt.demo;
import lombok.Data;
import org.bson.types.ObjectId;
@Data
public class DemoDo {
     private  ObjectId id;
    private String name;
    private  Integer  code;
    private SubDemo subDemo;
    @Data
    public  static  class SubDemo{
        private String id;
    }
}  
 package com.pt.demo;
import lombok.Data;
@Data
public class DemoDto {
    private String id;
    private String name;
    private Demo Enum  code;
    private SubDemo subDemo;
    @Data
    public static class SubDemo{
        private String id;
    }
}  
 package com.pt.demo;
import lombok.AllArgs Constructor ;
@AllArgsConstructor
public enum DemoEnum {
    BOY(1,"男"),
    GIRL(2,"女");
    int code;
    String value;
}  

最关键的一步来了,我们定义一个interface:DemoMapper

 package com.pt.demo;
import org.bson.types.ObjectId;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper(componentModel = "spring")
public interface DemoMapper {
    DemoMapper INSTANCE = Mappers.getMapper( DemoMapper.class );
    DemoDto convert(DemoDo demoDo);
    // 自定义转化,没需求可不加(对象转String)
    default String convert(ObjectId id){
        if(id == null){
            return null;
        }
        return id.toString();
    }
    // 自定义转化,没需求可不加(int co de转枚举)
    default DemoEnum convert(Integer code){
        return code == 1?DemoEnum.BOY:DemoEnum.GIRL;
    }
}  

解释:

  1. @Mapper(componentModel = “spring”) 指定是mapstruct的扫描接口,componentModel指定映射模式,默认是default,调用时使用接口上定义的单例( ItemMapper.INSTANCE.convert(itemDO); )也可以指定 spring 托管( @Mapper(componentModel = “spring”) ),调用时可直接使用 @Autowired。
  2. 对象名不一致,可在方法上加mapping注解( @Mapping(source = “id”,target = “itemId”) )。默认对象名相同时可自动转换。
  3. 类型不一致时,可在interface中定义default方法,自定义转换。如果是date转String,可以加入@mapping注解添加参数 dateFormat @Mapping(source = “localDate”,target = “localDate”,dateFormat = “yyyy-MM-dd”)

使用maven编译后,会在target里生成相应的代码。

我们测一下试试:

 package com.pt.demo;
import org.bson.types.ObjectId;
public class Test {
    public static  void  main(String[] args) {
        DemoDo demoDo = new DemoDo(ObjectId.get(),"ge",1,new DemoDo.SubDemo("1"));
        System.out.println(demoDo);
        DemoDto demoDto = DemoMapper.INSTANCE.convert(demoDo);
        System.out.println(demoDto);
    }
}  
 DemoDo(id=619f3aacb9b60d646f271b64, name=ge, code=1, subDemo=DemoDo.SubDemo(id=1))
DemoDto(id=619f3aacb9b60d646f271b64, name=ge, code=BOY, subDemo=DemoDto.SubDemo(id=1))

Process finished with exit code 0  

是不是很方便?这下再也不用担心晚上下不了班了。哈哈。适当地利用工具偷个懒,挺好。

文章来源:智云一二三科技

文章标题:还在纠结VO转换吗?试试MapStruct吧

文章地址:https://www.zhihuclub.com/199804.shtml

关于作者: 智云科技

热门文章

网站地图