1 序
mapstruct.pngMapStruct
是一个属性映射工具,只需要使用@Mapper
注解标注的映射接口。MapStruct
就会自动生成实现这个映射接口的实现类,避免了复杂繁琐的映射实现。MapStruct
官网地址: http://mapstruct.org/。
2 准备工作
2.1 定义映射示例Bean
- 定义Mode Bean
package com.eugeneheen.mapstruct.api.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class UserModel {
private Long id;
private String name;
private String phone;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime createTm;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
LocalDateTime updateTm;
}
- 定义Do Bean
package com.eugeneheen.mapstruct.dao.dataobject;
import lombok.Data;
import javax.persistence.*;
import java.time.LocalDateTime;
@Data
@Entity(name = "t_user")
public class UserDo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String name;
@Column
private String phone;
@Column(name = "create_tm")
LocalDateTime createTm;
@Column(name = "update_tm")
LocalDateTime updateTm;
}
2.2 示例使用的相关依赖
- Lombok
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<optional>true</optional>
</dependency>
- MapStruct官方依赖
<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>
<dependency>
<groupId>org.mapstruct.extensions.spring</groupId>
<artifactId>mapstruct-spring-annotations</artifactId>
<version>0.1.0</version>
</dependency>
- MapStruct第三方依赖
<dependency>
<groupId>io.github.zhaord</groupId>
<artifactId>mapstruct-spring-plus-boot-starter</artifactId>
<version>1.0.1.RELEASE</version>
</dependency>
3 示例
3.1 关于依赖
3.1.1 Maven
-
SpringBoot
单模块项目:直接在POM
文件加入相关依赖即可。 -
SpringBoot
多模块项目-
打包
的模块,POM
文件加入以下依赖:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.4.1</version> <configuration> <mainClass>com.eugeneheen.mapstruct.MapStructApplication</mainClass> <skip>false</skip> <layers> <enabled>true</enabled> </layers> <excludes> <!-- 打包的时候忽略lombok,解决生成了maptruct的实现类,但该类只创建了对象,没有进行赋值 --> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
- 定义
映射接口
的模块,POM
文件加入以下依赖:<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> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> <optional>true</optional> </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> <target>1.8</target> <encoding>UTF-8</encoding> <annotationProcessorPaths> <!-- 此处,lombok依赖一定要放在,Mapstruct-processor依赖之前。否则,生成了maptruct的实现类,但该类只创建了对象,没有进行赋值 --> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> </path> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.4.2.Final</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build>
-
3.1.2 Gradle
- version >= 4.6
dependencies {
implementation 'org.mapstruct:mapstruct:1.4.2.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'
}
- version < 4.6
plugins {
id 'net.ltgt.apt' version '0.21'
}
dependencies {
compile 'org.mapstruct:mapstruct:1.4.2.Final'
apt 'org.mapstruct:mapstruct-processor:1.4.2.Final'
}
3.2 基础使用示例
- 定义
映射接口
package com.eugeneheen.mapstruct.api.struct;
import com.yongyou.eshs.api.model.UserModel;
import com.yongyou.eshs.dao.dataobject.UserDo;
import org.mapstruct.Mapper;
@Mapper
public interface IUserStruct {
IUserStruct INSTANCE = Mappers.getMapper( IUserStruct.class );
UserDo modelToDo(UserModel userModel);
UserModel doToModel(UserDo user);
}
- 在
Service
中使用
public interface IUserService {
UserModel findById(Long id);
}
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private IUserRepository userRepository;
@Override
public UserModel findById(Long id) {
UserDo user = this.userRepository.getOne(id);
// 此处,由于映射定义未使用Spring注入,所以使用常量获实例再调用映射方法
return IUserStruct.INSTANCE.toModel(user);
}
}
3.3 注入到Spring的使用示例
- 定义
映射接口
package com.eugeneheen.mapstruct.api.struct;
import com.yongyou.eshs.api.model.UserModel;
import com.yongyou.eshs.dao.dataobject.UserDo;
import org.mapstruct.Mapper;
// 使用@Mapper注解的componentModel属性值制定为Spring,实现Spring注入
@Mapper(componentModel = "spring")
public interface IUserStruct {
UserDo modelToDo(UserModel userModel);
UserModel doToModel(UserDo user);
}
- 在
Service
中使用
public interface IUserService {
UserModel findById(Long id);
}
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private IUserRepository userRepository;
// 此处,注入由Spring管理的映射实现
@Autowired
private IUserStruct userStruct;
@Override
public UserModel findById(Long id) {
UserDo user = this.userRepository.getOne(id);
return this.userStruct.toModel(user);
}
}
3.4 使用Spring扩展依赖的使用示例
待续......
4 常见问题
4.1 Maven
构建出现生成了MapStruct的实现类,但该类只创建了对象,没有进行赋值的问题
- 定义
映射接口
的模块/工程,maven-compiler-plugin
插件,配置lombok-mapstruct-binding
依赖,且依赖版本由0.1.0
升级到0.2.0
<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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<optional>true</optional>
</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>
<target>1.8</target>
<encoding>UTF-8</encoding>
<annotationProcessorPaths>
<!-- 此处,lombok依赖一定要放在,Mapstruct-processor依赖之前。否则,生成了maptruct的实现类,但该类只创建了对象,没有进行赋值 -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<!-- 如果是0.1.0 有可能出现生成了MapStruct的实现类,但该类只创建了对象,没有进行赋值 -->
<version>0.2.0</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
-
多项目
打包时,在父项目/打包模块
的POM
中配置spring-boot-maven-plugin
插件时,排除``依赖。详细配置见3.1.1
章节,SpringBoot
多模块项目配置
5 MapStruct与各种BeanUtil性能比较
工具 | 十个对象复制1次 | 一万个对象复制1次 | 一百万个对象复制1次 | 一百万个对象复制5次 |
---|---|---|---|---|
MapStruct | 0ms | 3ms | 96ms | 281ms |
Hutool的BeanUtil | 23ms | 102ms | 1734ms | 8316ms |
Spring的BeanUtils | 2ms | 47ms | 726ms | 3676ms |
Apache的BeanUtils | 20ms | 156ms | 10658ms | 52355ms |
测试数据仅供参考,根据不同主机配置均有不同,单此处数据也能客观表现性能
网友评论