MapStruct

231 阅读5分钟

MapStruct

Mapsturct 是一个通过配置公约的一种代码生成器,它大大简化了Java Bean类型之间的映射的实现,而且类型安全,性能高,使用简单 这时有人会提到为什么不直接用Spring的BeanUtils,这里给大家做个简单概述:

如果两个对象之间存在不同字段,则不会对这些字段进行处理

如果两个对象之间字段类型不相同,则会导致类型转换异常

关键性能也比较低

image.png

当出现两个字段不一致就会导致复制失败

初步验证

1.引入依赖

<dependency>
    <groupId>org.mapstruct</groupId>
    <!-- jdk8以下就使用mapstruct -->
    <artifactId>mapstruct-jdk8</artifactId>
    <version>1.2.0.Final</version>
</dependency>

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-proceSSOr</artifactId>
    <version>1.2.0.Final</version>
</dependency>

2.定义mapper

/**
 * @Mapper 定义这是一个MapStruct对象属性转换接口,在这个类里面规定转换规则
 *          在项目构建时,会自动生成该接口的实现类,这个实现类将实现对象属性值复制
 * componentModel 属性,它的值就是当前要使用的依赖注入的环境
 */
@Mapper(componentModel = "Spring")
public interface StudentMapper {

    //默认加载方式
    StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
    
     /**
     * 这个方法就是用于实现对象属性复制的方法
     *
     * @Mapping 用来定义属性复制规则 source 指定源对象属性 target指定目标对象属性
     * @param students 这个参数就是源对象,也就是需要被复制的对象
     * @return 返回的是目标对象,就是最终的结果对象
     */
    @Mappings({
            @Mapping(source = "address", target = "addr")
    })
    StudentsVO students2StudentsVO(Students students);
}

3.验证

    Students students3 = new Students("一安未来3","北京",Arrays.asList(123));
    StudentsVO studentsVO3 = StudentMapper.INSTANCE.students2StudentsVO(students3);
    System.out.println("MapStruct:"+studentsVO3);
    List<String> ids = studentsVO3.getIds();
    for (String id:ids){
        System.out.println(id);
    }
    
    //运行
    MapStruct:StudentsVO(name=一安未来3, addr=北京, ids=[123])
    1
    2
    3

绑定多个对象的属性值

1.复制实体类Students--->Students2

2.定义mapper

/**
 * @Mapper 定义这是一个MapStruct对象属性转换接口,在这个类里面规定转换规则
 *          在项目构建时,会自动生成该接口的实现类,这个实现类将实现对象属性值复制
 * componentModel 属性,它的值就是当前要使用的依赖注入的环境
 */
@Mapper(componentModel = "spring")
public interface StudentMapper {
    //默认加载方式
    StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
    
     /**
     * 这个方法就是用于实现对象属性复制的方法
     *
     * @Mapping 用来定义属性复制规则 source 指定源对象属性 target指定目标对象属性
     * @param students 这个参数就是源对象,也就是需要被复制的对象
     * @return 返回的是目标对象,就是最终的结果对象
     */
    @Mappings({
            @Mapping(source = "address", target = "addr")
    })
    StudentsVO students2StudentsVO(Students students);

    @Mappings({
            @Mapping(source = "students.name", target = "name"),
            @Mapping(source = "students.address", target = "addr"),
            @Mapping(source = "students2.ids", target = "ids")
    })
    StudentsVO students2StudentsVO(Students students,Students2 students2);
}

3.验证

    Students students = new Students("一安未来3","北京",Arrays.asList(123));
    Students2 students2 = new Students2("一安未来3","北京",Arrays.asList(345));
    StudentsVO studentsVO3 = StudentMapper.INSTANCE.students2StudentsVO(students,students2);
    System.out.println("MapStruct:"+studentsVO3);
    
    //运行
    MapStruct:StudentsVO(name=一安未来3, addr=北京, ids=[345])

参数作为属性值

1.定义mapper

/**
 * @Mapper 定义这是一个MapStruct对象属性转换接口,在这个类里面规定转换规则
 *          在项目构建时,会自动生成该接口的实现类,这个实现类将实现对象属性值复制
 * componentModel 属性,它的值就是当前要使用的依赖注入的环境
 */
@Mapper(componentModel = "spring")
public interface StudentMapper {
    //默认加载方式
    StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
    
     /**
     * 这个方法就是用于实现对象属性复制的方法
     *
     * @Mapping 用来定义属性复制规则 source 指定源对象属性 target指定目标对象属性
     * @param students 这个参数就是源对象,也就是需要被复制的对象
     * @return 返回的是目标对象,就是最终的结果对象
     */
    @Mappings({
            @Mapping(source = "address", target = "addr")
    })
    StudentsVO students2StudentsVO(Students students);

    @Mappings({
            @Mapping(source = "students.name", target = "name"),
            @Mapping(source = "students.address", target = "addr"),
            @Mapping(source = "students2.ids", target = "ids")
    })
    StudentsVO students2StudentsVO(Students students,Students2 students2);


    @Mappings({
            @Mapping(source = "students.name", target = "name"),
            @Mapping(source = "students.address", target = "addr"),
            @Mapping(source = "param", target = "ids")
    })
    StudentsVO students2StudentsVO(Students students, List<String> param);
}

2.验证

    Students students = new Students("一安未来3","北京",Arrays.asList(123));
    StudentsVO studentsVO3 = StudentMapper.INSTANCE.students2StudentsVO(students,Arrays.asList("5""6""7"));
    System.out.println("MapStruct:"+studentsVO3);
    
    //运行
    MapStruct:StudentsVO(name=一安未来3, addr=北京, ids=[567])              

自定义类型转换

1.Students和StudentsVO增加gender字段:Students中为Integer类型 ,StudentsVO中为String类型

2.定义转换类

@Named("genderToString")
public class GenderToString {

    public String toStr(Integer gender) {
        if (gender==0) {
            return "Y";
        } else {
            return "N";
        }
    }

    public Integer toInt(String gender) {
        if ("Y".equals(gender)) {
            return 0;
        } else {
            return 1;
        }
    }
}

3.定义mapper

/**
 * @Mapper 定义这是一个MapStruct对象属性转换接口,在这个类里面规定转换规则
 * 在项目构建时,会自动生成改接口的实现类,这个实现类将实现对象属性值复制
 * componentModel 属性,它的值就是当前要使用的依赖注入的环境
 * 注意当componentModel为spring时,GenderToString也需要交给spring管理
 * uses属性支持设置多个
 */
@Mapper(uses = { GenderToString.class})
public interface StudentMapper {
    StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
    
     /**
     * 这个方法就是用于实现对象属性复制的方法
     *
     * @Mapping 用来定义属性复制规则 source 指定源对象属性 target指定目标对象属性
     * qualifiedByName指明转换类
     * @param students 这个参数就是源对象,也就是需要被复制的对象
     * @return 返回的是目标对象,就是最终的结果对象
     */
    @Mappings({
            @Mapping(source = "address", target = "addr"),
            @Mapping(source = "gender", target = "gender",qualifiedByName= {"genderToString"})
    })
    StudentsVO students2StudentsVO(Students students);

    @Mappings({
            @Mapping(source = "students.name", target = "name"),
            @Mapping(source = "students.address", target = "addr"),
            @Mapping(source = "students2.ids", target = "ids")
    })
    StudentsVO students2StudentsVO(Students students,Students2 students2);


    @Mappings({
            @Mapping(source = "students.name", target = "name"),
            @Mapping(source = "students.address", target = "addr"),
            @Mapping(source = "param", target = "ids")
    })
    StudentsVO students2StudentsVO(Students students, List<String> param);
}

4.验证

  Students students = new Students("一安未来3",0,"北京",Arrays.asList(123));
  StudentsVO studentsVO3 = StudentMapper.INSTANCE.students2StudentsVO(students);
  System.out.println("MapStruct:"+studentsVO3);
  
  //运行
  MapStruct:StudentsVO(name=一安未来3, gender=Y, addr=北京, ids=[123])

总结

Mapping源码中还有很多属性,比如支持日期格式化dateFormat,数字格式化numberFormat等操作

public @interface Mapping {
    String target();

    String source() default "";

    String dateFormat() default "";

    String numberFormat() default "";

    String constant() default "";

    String expression() default "";

    boolean ignore() default false;

    Class<? extends Annotation>[] qualifiedBy() default {};

    String[] qualifiedByName() default {};

    Class<?> resultType() default void.class;

    String[] dependsOn() default {};

    String defaultValue() default "";
}

摘自www.bmabk.com/index.php/p…