Human0722's blog Human0722's blog
首页
  • Spring

    • Spring Framework
    • Spring Boot
    • Spring Cloud
  • CCNA
  • Vue

    • Vue2
日本语
导航
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Human0722

Gravity always win
首页
  • Spring

    • Spring Framework
    • Spring Boot
    • Spring Cloud
  • CCNA
  • Vue

    • Vue2
日本语
导航
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Spring Framework

  • Spring Boot

  • Java 类库

    • Lombok
    • Mapstruct
      • Swagger
      • druid starter
      • Mybatis
      • Mybatis_Plus
    • 数据库

    • 解决方案

    • Java.Content
    • Java 类库
    Xueliang
    2022-06-06
    目录

    Mapstruct

    MapStruct

    # What is MapStruct

    MapStruct 可以通过注解配置的方法完成 JavaBean 之间的属性对拷。 其通过配置的方式统一管理 JavaBean 之间的拷贝关系, 虽然相对比 BeanUtils 这样的工具需要多一层配置,但是在大型项目中,遍布在各个角落的 BeanUtils 遇到修改的需求时,MapStruct 的优势就很明显了。
    另外, MapStruct 还支持更加灵活的属性拷贝方案,其性能也比 BeanUtils 要好很多。

    # Why MapStruct

    用为什么需要属性对拷来回答为什么需要 MapStruct 是个不错的方式。 在数据传输的过程中,用户往往不需要访问记录的所有属性。所以当从数据库中查询出一条记录时,需要将部分需要的属性重新封装成一个 JavaBean。 DTO(Data Transfer Object)就是一个例子。 此时往往需要大量的代码来执行 Model 到 Dto 的转换。

    当需要用一个 JavaBean 的属性值来初始化另外一个 JavaBean 时,Mapstruct 通过一次配置,即可快速的完成 JavaBean 转换。从而避免了大量的 A.setA(B.getA());代码。

    # How to use Mapstruct

    # Import

    <!-- 在 pom.xml 中配置 maven依赖 -->
    <dependencies>
        <dependency>
          <groupId>org.mapstruct</groupId>
          <artifactId>mapstruct</artifactId>
          <version>1.4.2.Final</version>
        </dependency>
        <dependency>
          <groupId>org.mapstruct</groupId>
          <artifactId>mapstruct-processor</artifactId>
          <version>1.4.2.Final</version>
        </dependency>
    </dependencies>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    # 基本映射

    /**
    * 模型类 Person
    */
    class Person {
        private Integer id;
        private String name;
    }
    
    /**
    * Dto
    */
    class PersonDto {
        private Integer id;
        private String name;
    }
    
    /**
    * 映射器
    */
    @org.mapstruct.Mapper
    public interface PersonMapper {
        PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
        
        PersonDto toDto(Person person);
    }
    
    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

    上面代码中三个类分别定义了 Person,PersonDto, PersonMapper。 当我们拥有 Person 实例的时候,可以通过下面的代码迅速获得 PersonDto 实例。

    PersonDto personDto = PersonMapper.INSTANCE.toDto(person);
    
    1

    # 自定义映射关系

    可以在方法上添加注解 @Mapping 来自定义映射关系。

    @Mapper
    public interface PersonMapper {
        PersonMapper INSTANCE = Mappers.getMapper(PersonMapper);
    
        @Mapping(source = "person.name", target = "id")
        PersonDto toDto(Person person);
    }
    
    1
    2
    3
    4
    5
    6
    7

    # 跳过空值覆盖

    @Mapper
    public interface PersonMapper {
        @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
        void toDomain(Person.Update update, @MappingTarget Person person);
    }
    
    1
    2
    3
    4
    5

    # 多个输入源

    MapStruct 支持将多个实例的属性值汇聚到一个实例内。

    @Mapper
    public interface PersonMapper {
        Personmapper INSTANCE = Mappers.getMapper(PersonMapper.class);
    
        @Mapping(source = "person.name", target = "name")
        @Mapping(source = "school.name", target = "school")
        PersonDto toDto(Person person, School school);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

    # 自动转换成员属性

    当我们有 A, ADto, B, BDto 四个类时。其中B类是这样的:

    class B {
        List<A> aList;
    }
    
    1
    2
    3

    如果我们期望的 BDto 内部是这样的:

    class BDto {
      List<ADto> aList;
    }
    
    1
    2
    3

    首先,我们要定义 A -> ADto 的映射关系:

    @Mapper
    public interface AMapper{
        AMapper m = Mappers.getMapper(AMapper.class);
        
        ADto toDto(A);
    }
    
    1
    2
    3
    4
    5
    6

    然后在定义 B -> BDto 时通过uses指令指定使用 AMapper 来处理成员变量的转换。

    @Mapper(uses = {AMapper.class})
    public interface BMapper {
        BMapper m = Mappers.getMapper(BMapper.class);
        
        BDto toDto(B);
    }
    
    // 可以直接通过下面获得含有 List<ADto> 的 BDTo 实例。
    BDto BDto = BMapper.INSTANCE.toDto(B);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    # 依赖注入

    直接将 Mapper 放入 Spring IOC 容器中。

    @Mapper(componentModel = "spring")
    public interface PersonMapper{}
    
    // 相当于
    @Component
    public class PersonMapperImpl implements PersonMapper{}
    
    1
    2
    3
    4
    5
    6

    可以通过@Autowired来自动注入。

    @RestController
    class HelloControlelr { 
        @Autowired
        private PersonMapper personMapper;
    }
    
    1
    2
    3
    4
    5

    # 自定义映射方法

    在 Mapper 接口中,使用 default 修饰方法名后,可以定义方法体,在方法体中定义转换的方法。

    @Mapper
    public interface Person {
      default PersonDto toDto(Person person) {
          retrun PersonDto.builder().id(person.getId()).name(person.getName()).build();
      }
    }
    
    1
    2
    3
    4
    5
    6

    也可以通过编写抽象类的方法来自定义转换方法。

    @Mapper
    public abstract class PersonMapper {
        public PersonDto toDto(Person person) {
            return PersonDto.builder().id(person.getId()).name(person.getName()).build();
        }
    }
    
    1
    2
    3
    4
    5
    6
    Lombok
    Swagger

    ← Lombok Swagger→

    最近更新
    01
    DefineSprintBootStarter
    03-23
    02
    Spring MVC 启动流程分析
    03-23
    03
    Redis
    03-23
    更多文章>
    Theme by Vdoing | Copyright © 2019-2024 Human0722 | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式