MapStruct使用指北

mapstruct官方文档链接,点击跳转

mapstruct是什么?

MapStruct 是一个代码生成器,它基于约定优于配置方法极大地简化了 Java bean 类型之间映射的实现。
生成的映射代码使用简单的方法调用,因此速度快、类型安全且易于理解。

为什么要使用mapstruct?

多层应用程序通常需要在不同的对象模型(例如实体和 DTO)之间进行映射。编写这样的映射代码是一项繁琐且容易出错的任务。MapStruct 旨在通过尽可能自动化来简化这项工作。
与其他映射框架相比,MapStruct 在编译时生成 bean 映射,这确保了高性能,允许快速的开发人员反馈和彻底的错误检查。

如何使用?

MapStruct 是一个注释处理器,它被插入到 Java 编译器中,可以在命令行构建(Maven、Gradle 等)中使用,也可以在 IDE 中使用。MapStruct 使用合理的默认值,但在配置或实现特殊行为时会避开您的方式。

入门案例

引入maven依赖

...
<properties>
    <org.mapstruct.version>1.5.3.Final</org.mapstruct.version>
</properties>
...
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
</dependencies>
...
<build>
    <plugins>
        <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 -->
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                    <!-- other annotation processors -->
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

实体类

/**
 * @author 云川
 * @description: 车 实体类
 * @date 2023/2/14 22:51
 */
public class Car {

    private String make;
    private int numberOfSeats;
    private CarType type;

    public Car() {
    }

    public Car(String make, int numberOfSeats, CarType type) {
        this.make = make;
        this.numberOfSeats = numberOfSeats;
        this.type = type;
    }

    public String getMake() {
        return make;
    }

    public void setMake(String make) {
        this.make = make;
    }

    public int getNumberOfSeats() {
        return numberOfSeats;
    }

    public void setNumberOfSeats(int numberOfSeats) {
        this.numberOfSeats = numberOfSeats;
    }

    public CarType getType() {
        return type;
    }

    public void setType(CarType type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return "Car{" +
                "make='" + make + '\'' +
                ", numberOfSeats=" + numberOfSeats +
                ", type=" + type +
                '}';
    }
}

CartType枚举类

/**
 * @author 云川
 * @description: 车的类型枚举值
 * @date 2023/2/14 22:52
 */
public enum CarType {
    TYPE_A, TYPE_B, TYPE_C;
}

DTO类

/**
 * @author 云川
 * @description: 车 dto类
 * @date 2023/2/14 23:01
 */
public class CarDto {

    private String make;
    private int seatCount;
    private String type;

    public CarDto() {
    }

    public CarDto(String make, int seatCount, String type) {
        this.make = make;
        this.seatCount = seatCount;
        this.type = type;
    }

    public String getMake() {
        return make;
    }

    public void setMake(String make) {
        this.make = make;
    }

    public int getSeatCount() {
        return seatCount;
    }

    public void setSeatCount(int seatCount) {
        this.seatCount = seatCount;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return "CarDto{" +
                "make='" + make + '\'' +
                ", seatCount=" + seatCount +
                ", type='" + type + '\'' +
                '}';
    }
}

创建映射器接口

上面的Car类和CarDTO这两种类型非常相似
不同点:

  1. 只是座位数属性的名称不同
  2. type 属性在Car类中是一个引用类型,Car但在 DTO 中是一个普通字符串。

现在想要把Car对象转换成CarDto对象,通过mapstruct实现,首先需要定义一个Mapper转换器

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

/**
 * @author 云川
 * @description: 转换器
 * @date 2023/2/14 23:07
 */
@Mapper
public interface CarMapper {

    CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );

    @Mapping(source = "numberOfSeats", target = "seatCount")
    CarDto carToCarDto(Car car);
}

在这里插入图片描述

使用映射器

基于映射器接口,客户端可以以非常简单且类型安全的方式执行对象映射:

/**
 * @author 云川
 * @description: 测试类
 * @date 2023/2/14 23:22
 */
public class MapStructTest {
    @Test
    public void shouldMapCarToDto() {
        //given
        Car car = new Car( "Morris", 5, CarType.TYPEA );

        //when
        CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );

        //then
        System.out.println(carDto);
    }
}

结果:
在这里插入图片描述

查看编译自动生成的接口实现类

可以看到编译之后自动生成了个实现类
在这里插入图片描述
字节码文件反编译:

public class CarMapperImpl implements CarMapper {
    public CarMapperImpl() {
    }

    public CarDto carToCarDto(Car car) {
        if (car == null) {
            return null;
        } else {
            CarDto carDto = new CarDto();
            carDto.setSeatCount(car.getNumberOfSeats());
            carDto.setMake(car.getMake());
            if (car.getType() != null) {
                carDto.setType(car.getType().name());
            }

            return carDto;
        }
    }
}

MapStruct的原理是生成和我们自己写的代码一样的代码,这意味着这些值是通过简单的getter/setter调用而不是反射或类似的方法从source类复制到target类的。使得MapStruct的性能会比动态框架更加优秀

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值