• MapStruct简单入门


    是什么?

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

    能做什么?

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

    怎么用?

    MapStruct 1.5.2.Final版本为例

    1. 引入依赖

          <dependency>
              <groupId>org.mapstructgroupId>
              <artifactId>mapstructartifactId>
              <version>1.5.2.Finalversion>
          dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
    2. build

      
      
      
       <build>
              <plugins>
                  <plugin>
                      <groupId>org.apache.maven.pluginsgroupId>
                      <artifactId>maven-compiler-pluginartifactId>
                      <version>3.8.1version>
                      <configuration>
                          <source>1.8source>
                          <target>1.8target>
                          <annotationProcessorPaths>
                              <path>
                                  <groupId>org.mapstructgroupId>
                                  <artifactId>mapstruct-processorartifactId>
                                  <version>1.5.2.Finalversion>
                              path>
                              <path>
                                  <groupId>org.projectlombokgroupId>
                                  <artifactId>lombokartifactId>
                                  <version>1.18.24version>
                              path>
                              <path>
                                  <groupId>org.projectlombokgroupId>
                                  <artifactId>lombok-mapstruct-bindingartifactId>
                                  <version>0.2.0version>
                              path>
                          annotationProcessorPaths>
                      configuration>
                  plugin>
              plugins>
          build>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
    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);
        
            /**
             * 
             * 1. 当一个属性与其对应的目标实体同名时,它将被隐式映射。
             * 2. 当一个属性在目标实体中具有不同的名称时,可以通过@Mapping注解指定其名称。
             * 
        * * @param student * @return */
        @Mapping(target = "studentName", source = "name") StudentDto student2StudentDto(Student student); }
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        //生成方法
            @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;
            }
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
    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;
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      
      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;
      
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
    • 多源参数映射

      // map参数
              Map<String, String> map = new HashMap<>();
              map.put("name", "ww");
              StudentDto studentDto1 = StudentConverter.INSTANCE.map2StudentDto(map);
              System.out.println(studentDto1);
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      // 映射方法内容
          @Mapping(target = "studentName", source = "name")
          StudentDto map2StudentDto(Map<String, String> map);
      
      • 1
      • 2
      • 3
      //生成的代码
      
          @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;
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
    • 嵌套映射

      // 嵌套
              StudentDto studentDto2 = StudentConverter.INSTANCE.nested2StudentDto(student);
              System.out.println(studentDto2);
      
      
      • 1
      • 2
      • 3
      • 4
      // 定义方法
          @Mapping(target = "courseName", source = "course.name")
          StudentDto nested2StudentDto(Student student);
      
      • 1
      • 2
      • 3
      // 生成代码
      
          @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;
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
    • 映射集合

       // 集合
              List<StudentDto> studentDto3 = StudentConverter1.INSTANCE.students2StudentDtos(Lists.newArrayList(student));
              System.out.println(studentDto3);
      
      • 1
      • 2
      • 3
      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);
      
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      //生成代码
       @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;
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
    • 高级用法

      • 默认值和常量
      @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);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 表达式
      @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);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      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);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 默认表达式
      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
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

    总结

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

    参考

    https://mapstruct.org

  • 相关阅读:
    PCB测试四大方式你都了解吗?DFM的重要性不容忽视
    解决redis从服务器未配置主服务器密码导致数据未同步&磁盘爆满问题
    gitlab安装在虚拟机下,使用gitlabrunner通过宿主机网络访问
    2022 年你必须准备的 115 个 SQL 面试问题
    QT:搭配tablewidget的数据库编程
    如何提高文章质量,不被发文助手“推荐受影响”
    SpringBoot事件发布监听
    【竞技宝】DOTA2-梦幻联赛S22:AR命悬一线 XG确定晋级淘汰赛
    2022年软件测试人员必读的经典书籍推荐(附电子版)
    好心情平台:看精神科医生前必知的5件事!让你少花钱少受罪
  • 原文地址:https://blog.csdn.net/stxyg/article/details/126652954