1. MapStruct是什么
MapStruct是一个功能强大且性能很高的Bean映射工具,项目开发中难免会涉及各种Bean的转换,DTO->VO->Entity。
市面上能做转换的框架很多,以前我们常用的可能是BeanUtils.copyProperties
,其核心是在运行时根据反射动态赋值。动态方案的缺陷在于大量的反射调用,性能比较差,内存占用多,不适合特别高并发的应用场景。
而MapStruct通过注解,在编译时静态生成映射代码,其最终编译出来的代码和手写的代码在性能上完全一致,且有强大的注解等能力。如果你的IDE支持,甚至可以在编译后看到编译出来的映射代码,用来做check。
下面给出一张性能对比.
很明显MapStruct和JMapper的性能是最优异的
2. MapStruct如何使用
.如果报错可以尝试不要使用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的一起使用