Java项目整合MapStruct
作为一个Java开发程序员,在编写代码的过程中,几乎不能避免不同对象之间的映射和转换,无论是一对一还是一对多的映射,一般都是DO/DTO/VO/ENTITY之间的映射。
市面上也有很多这样的工具,如BeanUtils、Hutool、Dozer工具包等,但是各个工具的效率和性能也是良莠不齐,大家可以参考如下这篇文章。
从上文的真实测试中,我们可以知道,性能最好的就是MapStruct。
简而言之, MapStruct 是一个生成类型安全,高性能且无依赖的,基于约定优于配置的JavaBean映射代码的注解处理器。
下面我们就介绍一下 MapStruct 的常用操作。
POM配置
POM配置如下。
JDK版本号是11.0.17。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ylz</groupId>
<artifactId>mapstruct-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mapstruct-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<jdk11.version>11</jdk11.version>
<mapstruct-version>1.5.3.Final</mapstruct-version>
<lombok>1.18.24</lombok>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct-version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${jdk11.version}</source>
<target>${jdk11.version}</target>
<annotationProcessorPaths>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok}</version>
</path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct-version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
代码结构
代码结果如下图。
我们首先创建Student实体类以及对应的StudentDTO类。
Student.java代码如下。
package com.ylz.mapstruct.domain.entity;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
public class Student {
private Long id;
private String name;
private String idCard;
private LocalDate birthday;
StudentDTO.java代码如下。
package com.ylz.mapstruct.domain.dto;
import lombok.Data;
import java.time.LocalDate;
@Data
public class StudentDTO {
private Long userId;
private String userName;
private String idNumber;
private LocalDate dateOfBirth;
}
示例代码
IStudentConvert.java代码如下。
package com.ylz.mapstruct.domain.convert;
import com.ylz.mapstruct.domain.dto.StudentDTO;
import com.ylz.mapstruct.domain.entity.Student;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
@Mapper
public interface IStudentConvert {
IStudentConvert INSTANCE = Mappers.getMapper(IStudentConvert.class);
@Mapping(source = "id", target = "userId")
@Mapping(source = "name", target = "userName")
@Mapping(source = "idCard", target = "idNumber")
@Mapping(source = "birthday", target = "dateOfBirth")
StudentDTO student2StudentDTO(Student student);
@Mapping(source = "userId", target = "id")
@Mapping(source = "userName", target = "name")
@Mapping(source = "idNumber", target = "idCard")
@Mapping(source = "dateOfBirth", target = "birthday")
Student studentDTO2Student(StudentDTO studentDTO);
单元测试代码如下。
package com.ylz.mapstruct;
import com.ylz.mapstruct.domain.convert.IStudentConvert;
import com.ylz.mapstruct.domain.dto.StudentDTO;
import com.ylz.mapstruct.domain.entity.Student;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDate;
@SpringBootTest
class MapstructDemoApplicationTests {
@Test
void test() {
StudentDTO studentDTO = new StudentDTO();
studentDTO.setUserId(0L);
studentDTO.setUserName("jack");
studentDTO.setIdNumber("1111");
studentDTO.setDateOfBirth(LocalDate.now());
System.out.println(IStudentConvert.INSTANCE.studentDTO2Student(studentDTO));
Student student = new Student();
student.setId(1L);
student.setName("michael");
student.setIdCard("22222");
student.setBirthday(LocalDate.now());
System.out.println(IStudentConvert.INSTANCE.student2StudentDTO(student));
在执行单元测试仿方法之前,还有关键一步要操作—— 编译 !
我们可以通过命令行方式编译,也可以通过上图双击compile按钮编译。
编译完成后,在上图中的指定目录会生成一个IStudentConvertImpl.class类,其代码如下所示。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
package com.ylz.mapstruct.domain.convert;
import com.ylz.mapstruct.domain.dto.StudentDTO;
import com.ylz.mapstruct.domain.entity.Student;
public class IStudentConvertImpl implements IStudentConvert {
public IStudentConvertImpl() {
public StudentDTO student2StudentDTO(Student student) {
if (student == null) {
return null;
} else {
StudentDTO studentDTO = new StudentDTO();
studentDTO.setUserId(student.getId());
studentDTO.setUserName(student.getName());
studentDTO.setIdNumber(student.getIdCard());
studentDTO.setDateOfBirth(student.getBirthday());
return studentDTO;
public Student studentDTO2Student(StudentDTO studentDTO) {
if (studentDTO == null) {
return null;
} else {
Student student = new Student();
student.setId(studentDTO.getUserId());
student.setName(studentDTO.getUserName());