1. MapStruct是什么

MapStruct是一个功能强大且性能很高的Bean映射工具,项目开发中难免会涉及各种Bean的转换,DTO->VO->Entity。

市面上能做转换的框架很多,以前我们常用的可能是​​BeanUtils.copyProperties​​,其核心是在运行时根据反射动态赋值。动态方案的缺陷在于大量的反射调用,性能比较差,内存占用多,不适合特别高并发的应用场景。

而MapStruct通过注解,在编译时静态生成映射代码,其最终编译出来的代码和手写的代码在性能上完全一致,且有强大的注解等能力。如果你的IDE支持,甚至可以在编译后看到编译出来的映射代码,用来做check。

下面给出一张性能对比.

Bean映射工具MapStruct介绍_MapStruct

很明显MapStruct和JMapper的性能是最优异的

2. MapStruct如何使用

Bean映射工具MapStruct介绍_html_02

.如果报错可以尝试不要使用Lombok注解

2.1 基础使用

2.1.1 导包

<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>

​commons-lang3​​不是必须的,此处只是为了演示

2.1.2 写几个测试类

Person

package com.bxoon.mapstruct;


import java.util.Date;

public class Person {
private Long id;
private String name;
private String email;
private Date birthday;
private User user;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public Date getBirthday() {
return birthday;
}

public void setBirthday(Date birthday) {
this.birthday = birthday;
}

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}

public Person(Long id, String name, String email, Date birthday, User user) {
this.id = id;
this.name = name;
this.email = email;
this.birthday = birthday;
this.user = user;
}

public Person() {
}
}

PersonDTO

package com.bxoon.mapstruct;


import java.util.Date;

public class PersonDTO {
private Long id;
private String name;
/**
* 对应 Person.user.age
*/
private Integer age;
private String email;
/**
* 与 DO 里面的字段名称(birthDay)不一致
*/
private Date birth;
/**
* 对 DO 里面的字段(birthDay)进行拓展,dateFormat 的形式
*/
private String birthDateFormat;
/**
* 对 DO 里面的字段(birthDay)进行拓展,expression 的形式
*/
private String birthExpressionFormat;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public Date getBirth() {
return birth;
}

public void setBirth(Date birth) {
this.birth = birth;
}

public String getBirthDateFormat() {
return birthDateFormat;
}

public void setBirthDateFormat(String birthDateFormat) {
this.birthDateFormat = birthDateFormat;
}

public String getBirthExpressionFormat() {
return birthExpressionFormat;
}

public void setBirthExpressionFormat(String birthExpressionFormat) {
this.birthExpressionFormat = birthExpressionFormat;
}

public PersonDTO(Long id, String name, Integer age, String email, Date birth, String birthDateFormat, String birthExpressionFormat) {
this.id = id;
this.name = name;
this.age = age;
this.email = email;
this.birth = birth;
this.birthDateFormat = birthDateFormat;
this.birthExpressionFormat = birthExpressionFormat;
}

public PersonDTO() {
}
}
public class User {
private Integer age;

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

public User(Integer age) {
this.age = age;
}

public User() {
}
}

PersonConverter

package com.bxoon.mapstruct;

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

import java.util.List;

@Mapper
public interface PersonConverter {
PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);
@Mappings({
@Mapping(source = "birthday", target = "birth"),
@Mapping(source = "birthday", target = "birthDateFormat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
@Mapping(target = "birthExpressionFormat", expression = "java(org.apache.commons.lang3.time.DateFormatUtils.format(person.getBirthday(),\"yyyy-MM-dd HH:mm:ss\"))"),
@Mapping(source = "user.age", target = "age"),
@Mapping(target = "email", ignore = true)
})
PersonDTO domain2dto(Person person);

List<PersonDTO> domain2dto(List<Person> people);
}

写一个测试类使用

package com.bxoon.shardingspheredemo;

import com.bxoon.mapstruct.Person;
import com.bxoon.mapstruct.PersonConverter;
import com.bxoon.mapstruct.PersonDTO;
import com.bxoon.mapstruct.User;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

public class PersonConverterTest {
@Test
public void test() {
Person person = new Person(1L,"zhige","zhige.me@gmail.com",new Date(),new User(1));
PersonDTO personDTO = PersonConverter.INSTANCE.domain2dto(person);
assertNotNull(personDTO);
assertEquals(personDTO.getId(), person.getId());
assertEquals(personDTO.getName(), person.getName());
assertEquals(personDTO.getBirth(), person.getBirthday());
String format = DateFormatUtils.format(personDTO.getBirth(), "yyyy-MM-dd HH:mm:ss");
assertEquals(personDTO.getBirthDateFormat(),format);
assertEquals(personDTO.getBirthExpressionFormat(),format);

List<Person> people = new ArrayList<>();
people.add(person);
List<PersonDTO> personDTOs = PersonConverter.INSTANCE.domain2dto(people);
assertNotNull(personDTOs);

}
}

MapStruct还有很多种用法,比如可以把多个对象聚合转为一个对象,比如联合springboot的一起使用