MAPSTRUCT(@Mapper用法)简单介绍

MAPSTRUCT(@Mapper用法)
img

官网地址:http://mapstruct.org/
MapStruct是一个代码生成器,简化了不同的Java Bean之间映射的处理,所以映射指的就是从一个实体变化成一个实体。例如我们在实际开发中,DAO层的实体和一些数据传输对象(DTO),大部分属性都是相同的,只有少部分的不同,通过mapStruct,可以让不同实体之间的转换变的简单。我们只需要按照约定的方式进行配置即可。
MapStruct是一个可以处理注解的Java编译器插件,可以在命令行中使用,也可以在IDE中使用。MapStruct有一些默认配置,但是也为用户提供了自己进行配置的途径。

1. 开发环境搭建–基于Maven

MapStruct主要由两部分组成:
org.mapstruct:mapstruct:包含了一些必要的注解,例如@Mapping。我们使用的JDK版本高于1.8,当我们在pom里面导入依赖时候,建议使用坐标是:org.mapstruct:mapstruct-jdk8,这可以帮助我们利用一些Java8的新特性。
org.mapstruct:mapstruct-processor:注解处理器,根据注解自动生成mapper的实现。

...
<properties>
    <org.mapstruct.version>1.1.0.Beta1</org.mapstruct.version></properties>
...
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-jdk8</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
    <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
 </dependencies>
...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins></build>
...
2 MapStruct2分钟入门

下面的代码演示了如何使用Map Struct实现Java Bean之间的映射。假设我们有一个表示汽车的类Car,并且还有一个数据传输对象(DTO)CarDTO。
这两个类非常相似,只是表示作为数量的属性名称是不同的并且,在Car对象中,表示汽车类型的字段是一个枚举,而在CarDTO中,直接使用字符串表示。
Car.java

public class Car {
    private String make;
    private int numberOfSeats;
    private CarType type;
    //constructor, getters, setters etc.
    }
    
  static enum CarType {
    SEDAN
}
12345678910

CarDTO.java

public class CarDto {
 
    private String make;
    private int seatCount;
    private String type;
 
    //constructor, getters, setters etc.
}
12345678
2.1 Mapper接口

要生成一个CarDTO与Car对象相互转换的映射器,我们需要定义一个mapper接口。
CarMapper.java

@Mapper 1
public interface CarMapper {
 
    CarMapper INSTANCE = Mappers.getMapper( CarMapper.class ); 3
 
    @Mapping(source = "numberOfSeats", target = "seatCount")
    //多个可以是用@mappings{@mapping(source="a",target="b")}
    CarDto carToCarDto(Car car); 2
}
12345678

1、@Mapper注解标记这个接口作为一个映射接口,并且是编译时MapStruct处理器的入口。

2、真正实现映射的方法需要源对象作为参数,并返回目标对象。映射方法的名字是随意的。对于在源对象和目标对象中,属性名字不同的情况,可以通过@Mapping注解来配置这些名字。我们也可以将源类型与目标类型中类型不同的参数进行转换,在这里就是通过type属性将枚举类型转换为一个字符串。当然在一个接口里可以定义多个映射方法。MapStruct都会为其生成一个实现。

3、自动生成的接口的实现可以通过Mapper的class对象获取。按照惯例,接口中会声明一个成员变量INSTANCE,从而让客户端可以访问Mapper接口的实现。

2.2 编译

因为MapStruct是以Java编译器插件的形式来处理注解,生成mapper接口的实现。因此在使用之前我们必须手工的编译(IDE的自动编译功能不会使用到MapStruct这个插件功能)。

执行maven命令:mvn compile

可以看到在target目录来多个一个类CarMapperImpl.class,如下图所示:

img

这个类实际上就是map struct插件自动帮助我们根据CarMapper接口生成的实现类。我们可以通过IDE的反编译功能查看自动生成的实现类的源码,如下图所示:

img

通过反编译的源码,我们可以看出,对于属性名称不同的情况(seatCount与numberOfSeats)、以及属性类型不同(枚举类型的type与字符串类型的type)都自动帮助我们转换了。对于属性名称不同的转换,我们是通过在@Mapping注解指定的,而不同属性类型的转换,这是MapStruct的默认配置。个人感觉这个很好,很强大。

2.3 使用Mapper

CarMapperTest.java

public class CarMapperTest {
    @Test
    public void shouldMapCarToDto() {
//given
        Car car = new Car( "Morris", 5, CarType.SEDAN );
 
//when
        CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
 
//then
        Assert.assertNotNull(carDto);
        Assert.assertEquals(carDto.getMake(),"Morris");
        Assert.assertEquals(carDto.getSeatCount() ,5);
        Assert.assertEquals(carDto.getType() ,"SEDAN");
    }
 
}
1234567891011121314151617

运行这个单元测试,如果没有报错的话,就说明我们已经成功运行这个案例了

3.mapper注解补充

1、@Mapper注解的componentModel属性
componentModel属性用于指定自动生成的接口实现类的组件类型。这个属性支持四个值:
default: 这是默认的情况,mapstruct不使用任何组件类型, 可以通过Mappers.getMapper(Class)方式获取自动生成的实例对象。
cdi: the generated mapper is an application-scoped CDI bean and can be retrieved via @Inject
spring: 生成的实现类上面会自动添加一个@Component注解,可以通过Spring的 @Autowired方式进行注入
jsr330: 生成的实现类上会添加@javax.inject.Named 和@Singleton注解,可以通过 @Inject注解获取。
我们以spring组件方式进行验证,将上一节的CarMapper接口上@Mapper注解添加componentModel属性,如下:

//设置组件模型为Spring
@Mapper(componentModel = "spring")
public interface CarMapper {
 
    CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
 
    @Mapping(source = "numberOfSeats", target = "seatCount")
    CarDto carToCarDto(Car car);
}
123456789

需要注意的是,当指定组件模型为Spring的时候,我们在classpath下一定要引入spring的jar包,否则MapStruct在编译的时候会报错。

现在再次执行"mvn compile",通过IDE反编译功能查看自动生成的Mapper实现类源码。
在这里插入图片描述

可以看到自动生成的实现类中,自动帮我们添加了@Component注解。因此我们在其他地方可以通过@AutoWired的方式自动注入。

参考博客:
博客1:
https://blog.csdn.net/qq_43459184/article/details/103372901
博客2:
https://blog.csdn.net/qq_43459184/article/details/103372740?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161588745816780262542319%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=161588745816780262542319&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-1-103372740.first_rank_v2_pc_rank_v29&utm_term=MapStruct%E4%B8%AD%E7%9A%84%40mapper

  • 16
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值