对象转换工具MapStruct

157 阅读1分钟

对于JAVA开发时,不同DTO、BO、PO、VO对象的转换是一个问题。MapStruct可以帮助开发者快速的进行类型转换,比如快速的将一个VO转为DTO。

SPringboot集成MapStruct

首先在Sprongboot项目的pom文件中引入MapStruct的依赖。版本兼容性问题: 使用不兼容的MapStruct版本可能导致内部处理器错误。

<!--MapStruct 依赖-->
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.4.1.Final</version>
</dependency>
<!--MapStruct 注解处理器-->
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.4.1.Final</version>
</dependency>

接着引入lombok的依赖。

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <scope>provided</scope>
</dependency>

测试用例:假设有一个Person类和一个Adderss类。目标是要将Person类和Adderss类的属性数据全部转入到DeliverAdderss类中。 首先定义一个AddressMapper接口。

@Mapper
public interface AddressMapper {
    //获取AddressMapper的实现类。实现类是编译时动态生成的。生成后的实现类会存放在target目录下。
    AddressMapper INSTANCE = Mappers.getMapper(AddressMapper.class);

    //定义将Person类和Address类映射到DeliveryAddress类的具体细节
    @Mappings(
            {
                    @Mapping(source = "person.description", target = "description"),
                    @Mapping(source = "address.houseNo", target = "houseNumber")
            }
    )
    //这个转换方法将Person和Address对象转换为DeliveryAddress对象。只需要声明这个方法即可。具体实现会在AddressMapper接口的动态实现类中
    DeliveryAddress personAndAddressToDeliveryAddressDto(Person person, Address address);
}

再编写一个单元测试。

@SpringBootTest
class MapstructApplicationTests {

    @Test
    void contextLoads() {
        Person person = new Person();
        person.setFirstName("John");
        person.setLastName("Doe");
        person.setHeight(180);
        person.setDescription("I'm a person");

        Address address = new Address();
        address.setStreet("Street");
        address.setZipCode(12345);
        address.setHouseNo(123);
        address.setDescription("I'm an address");
        DeliveryAddress deliveryAddress = AddressMapper.INSTANCE.personAndAddressToDeliveryAddressDto(person, address);
        System.out.println(deliveryAddress);
    }

输出转化后deliveryAddress的结果: DeliveryAddress(firstName=John, lastName=Doe, height=180, street=Street, zipCode=12345, houseNumber=123, description=I'm a person)

在target目录中可以找到转换工具MapStruct为AddressMapper编译时动态生成的实现类。实现类中实现了personAndAddressToDeliveryAddressDto这个方法。

public class AddressMapperImpl implements AddressMapper {

    @Override
    public DeliveryAddress personAndAddressToDeliveryAddressDto(Person person, Address address) {
        if ( person == null && address == null ) {
            return null;
        }

        DeliveryAddress deliveryAddress = new DeliveryAddress();

        if ( person != null ) {
            deliveryAddress.setDescription( person.getDescription() );
            deliveryAddress.setFirstName( person.getFirstName() );
            deliveryAddress.setLastName( person.getLastName() );
            deliveryAddress.setHeight( person.getHeight() );
        }
        if ( address != null ) {
            deliveryAddress.setHouseNumber( address.getHouseNo() );
            deliveryAddress.setStreet( address.getStreet() );
            deliveryAddress.setZipCode( address.getZipCode() );
        }

        return deliveryAddress;
    }
}