MapStruct简单入门

是什么?

一个java注释处理器,用于生成类型安全、高性能和无依赖关系的 bean 映射代码。

能做什么?

  1. 对象的映射,如user映射为userDto。
  2. 对象字段的转换,如applyType=1,转换为ipTypeCn=创建。

怎么用?

以MapStruct 1.5.2.Final版本为例

  1. 引入依赖

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.5.2.Final</version>
        </dependency>
    
  2. build

    
    
    
     <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>org.mapstruct</groupId>
                                <artifactId>mapstruct-processor</artifactId>
                                <version>1.5.2.Final</version>
                            </path>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                                <version>1.18.24</version>
                            </path>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok-mapstruct-binding</artifactId>
                                <version>0.2.0</version>
                            </path>
                        </annotationProcessorPaths>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
  3. 代码步骤

    • 定义接口或者抽象类实现映射器,并增加对应注解

    • 定义映射方法

    • 如:

      package cn.cnn.bean.mapstruct;
      
      import org.mapstruct.Mapper;
      import org.mapstruct.Mapping;
      import org.mapstruct.factory.Mappers;
      
      /**
       * @author ningning.cheng
       * @since 2022/8/28
       **/
      @Mapper
      public interface StudentConverter {
          StudentConverter INSTANCE = Mappers.getMapper(StudentConverter.class);
      
          /**
           * <pre>
           * 1. 当一个属性与其对应的目标实体同名时,它将被隐式映射。
           * 2. 当一个属性在目标实体中具有不同的名称时,可以通过@Mapping注解指定其名称。
           * </pre>
           * 
           * @param student
           * @return
           */
          @Mapping(target = "studentName", source = "name")
          StudentDto student2StudentDto(Student student);
      
      }
      
      
      //生成方法
          @Override
          public StudentDto student2StudentDto(Student student) {
              if ( student == null ) {
                  return null;
              }
      
              StudentDto studentDto = new StudentDto();
      
              studentDto.setStudentName( student.getName() );
              studentDto.setAge( student.getAge() );
      
              return studentDto;
          }
      
      
  4. 用法举例

    实体类:

    package cn.cnn.bean.mapstruct;
    
    import lombok.Data;
    
    /**
     * @author ningning.cheng
     * @since 2022/8/28
     **/
    @Data
    public class Student {
        private String name;
        private Integer age;
        private Course course;
    
        public Student() {}
    
        public Student(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    }
    
    
    
    package cn.cnn.bean.mapstruct;
    
    import lombok.Data;
    
    /**
     * @author ningning.cheng
     * @since 2022/8/28
     **/
    @Data
    public class StudentDto {
        private String studentName;
        private Integer age;
    
        private String courseName;
    
    }
    
    
  • 多源参数映射

    // map参数
            Map<String, String> map = new HashMap<>();
            map.put("name", "ww");
            StudentDto studentDto1 = StudentConverter.INSTANCE.map2StudentDto(map);
            System.out.println(studentDto1);
    
    
    // 映射方法内容
        @Mapping(target = "studentName", source = "name")
        StudentDto map2StudentDto(Map<String, String> map);
    
    //生成的代码
    
        @Override
        public StudentDto map2StudentDto(Map<String, String> map) {
            if ( map == null ) {
                return null;
            }
    
            StudentDto studentDto = new StudentDto();
    
            if ( map.containsKey( "name" ) ) {
                studentDto.setStudentName( map.get( "name" ) );
            }
            if ( map.containsKey( "age" ) ) {
                studentDto.setAge( Integer.parseInt( map.get( "age" ) ) );
            }
    
            return studentDto;
        }
    
  • 嵌套映射

    // 嵌套
            StudentDto studentDto2 = StudentConverter.INSTANCE.nested2StudentDto(student);
            System.out.println(studentDto2);
    
    
    // 定义方法
        @Mapping(target = "courseName", source = "course.name")
        StudentDto nested2StudentDto(Student student);
    
    // 生成代码
    
        @Override
        public StudentDto nested2StudentDto(Student student) {
            if ( student == null ) {
                return null;
            }
    
            StudentDto studentDto = new StudentDto();
    
            studentDto.setCourseName( studentCourseName( student ) );
            studentDto.setAge( student.getAge() );
    
            return studentDto;
        }
    
        private String studentCourseName(Student student) {
            if ( student == null ) {
                return null;
            }
            Course course = student.getCourse();
            if ( course == null ) {
                return null;
            }
            String name = course.getName();
            if ( name == null ) {
                return null;
            }
            return name;
        }
    
  • 映射集合

     // 集合
            List<StudentDto> studentDto3 = StudentConverter1.INSTANCE.students2StudentDtos(Lists.newArrayList(student));
            System.out.println(studentDto3);
    
    package cn.cnn.bean.mapstruct;
    
    import java.util.List;
    
    import org.mapstruct.Mapper;
    import org.mapstruct.factory.Mappers;
    
    /**
     * @author ningning.cheng
     * @since 2022/8/28
     **/
    @Mapper
    public interface StudentConverter1 {
        StudentConverter1 INSTANCE = Mappers.getMapper(StudentConverter1.class);
    
        List<StudentDto> students2StudentDtos(List<Student> students);
    
    }
    
    
    //生成代码
     @Override
        public List<StudentDto> students2StudentDtos(List<Student> students) {
            if ( students == null ) {
                return null;
            }
    
            List<StudentDto> list = new ArrayList<StudentDto>( students.size() );
            for ( Student student : students ) {
                list.add( studentToStudentDto( student ) );
            }
    
            return list;
        }
    
        protected StudentDto studentToStudentDto(Student student) {
            if ( student == null ) {
                return null;
            }
    
            StudentDto studentDto = new StudentDto();
    
            studentDto.setAge( student.getAge() );
    
            return studentDto;
        }
    
  • 高级用法

    • 默认值和常量
    @Mapper
    public interface SourceTargetMapper {
    
        SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
    
        @Mapping(target = "stringProperty", source = "stringProp", defaultValue = "undefined")
        @Mapping(target = "longProperty", source = "longProp", defaultValue = "-1")
        @Mapping(target = "stringConstant", constant = "Constant Value")
        @Mapping(target = "integerConstant", constant = "14")
        @Mapping(target = "longWrapperConstant", constant = "3001")
        @Mapping(target = "dateConstant", dateFormat = "dd-MM-yyyy", constant = "09-01-2014")
        @Mapping(target = "stringListConstants", constant = "jack-jill-tom")
        Target sourceToTarget(Source s);
    }
    
    • 表达式
    @Mapper
    public interface SourceTargetMapper {
    
        SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
    
        @Mapping(target = "timeAndFormat",
             expression = "java( new org.sample.TimeAndFormat( s.getTime(), s.getFormat() ) )")
        Target sourceToTarget(Source s);
    }
    
    imports org.sample.TimeAndFormat;
    
    @Mapper( imports = TimeAndFormat.class )
    public interface SourceTargetMapper {
    
        SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
    
        @Mapping(target = "timeAndFormat",
             expression = "java( new TimeAndFormat( s.getTime(), s.getFormat() ) )")
        Target sourceToTarget(Source s);
    }
    
    • 默认表达式
    imports java.util.UUID;
    
    @Mapper( imports = UUID.class )
    public interface SourceTargetMapper {
    
        SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
    
        @Mapping(target="id", source="sourceId", defaultExpression = "java( UUID.randomUUID().toString() )")
        Target sourceToTarget(Source s);
    }
    

总结

  1. 与动态映射框架相比,MapStruct 具有以下优点:
  • 通过使用普通方法调用而不是反射来快速执行
  • 编译时类型安全:只能映射相互映射的对象和属性。
  • 在构建时清除错误报告,如果
    • 映射不完整(并非所有目标属性都已映射)
    • 映射不正确(找不到合适的映射方法或类型转换)
  1. 缺点:
  • 通过在开发中生成源代码的方式实现,所以对于动态对象数据拷贝并不适合。

参考

https://mapstruct.org

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值