是什么?
是一个类转换框架,用于将do-->vo。这种的相互转换,替换BeanUtils的copy方法
为什么选他?
1、抽象出来转换接口,方便维护
2、可读性高,几个注解即可
3、性能高,其原理是在编译时期,将接口实现,而不是通过反射获取属性调用接口。
怎么用?
maven
<properties>
<org.mapstruct.version>1.3.1.Final</org.mapstruct.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</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> <!-- depending on your project -->
<target>1.8</target> <!-- depending on your project -->
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<!-- other annotation processors -->
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
定义do
@AllArgsConstructor
@NoArgsConstructor
@Data
public class PersonDO {
private Integer id;
private String name;
private int age;
private Date birthday;
private String gender;
private Integer version;
private String content;
}
定义vo
@AllArgsConstructor
@NoArgsConstructor
@Data
public class PersonVO {
private String userName;
private Integer age;
private String birthday;
private Gender gender;
private Integer version;
private String versionTitle;
private String content;
}
定义枚举Gender
@AllArgsConstructor
public enum Gender {
MAN(1, "男"),
WOMAN(2, "女") ;
需求:将do转换为vo,要求如下
①其中name显示为userName
②birthday转为 "yyyy-MM-dd HH:mm:ss"格式
③gender转为枚举
④versionTitle组成是="V"+version
⑤content固定输出为 “默认不变”
实现需求,创建PersonConverter
@Mapper
public interface PersonConverter {
PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);
//名称转化
@Mapping(source = "name", target = "userName")
//日期转化
@Mapping(target = "birthday",dateFormat = "yyyy-MM-dd HH:mm:ss")
//调用方法转换字段,注意其中的person为入参的形参{person}
@Mapping(target = "versionTitle",expression = "java(versionConvert(person.getVersion()))")
//固定一个字段不变
@Mapping(target = "content",constant = "默认不变")
PersonDTO do2dto(PersonDO person);
//转换versionTitle
default String versionConvert(Integer version){
return "V" + version;
}
}
小记:试想一下,转换通常不能使用通用方法进行转化,每个接口有每个接口想返回的vo,可能一个do设置多个vo进行展示,我们使用一个converter接口对应一个do,将所有的
do-->vo都在这里声明,方便维护
测试一下
public static void main(String[] args) {
PersonDO personDO = new PersonDO();
personDO.setName("Hollis");
personDO.setAge(26);
personDO.setBirthday(new Date());
personDO.setId(1);
personDO.setContent("初始");
personDO.setGender(Gender.MAN.name());
personDO.setVersion(1);
PersonVO personVO = PersonConverter.INSTANCE.do2dto(personDO);
System.out.println("do----->>>>>"+personDO);
System.out.println("VO----->>>>>"+personVO);
}
输出结果
do----->>>>>PersonDO(id=1, name=Hollis, age=26, birthday=Tue Aug 18 16:20:46 CST 2020, gender=MAN, version=1, content=初始)
dto----->>>>>PersonDTO(userName=Hollis, age=26, birthday=2020-08-18 16:20:46, gender=MAN, version=1, versionTitle=V1, content=默认不变)
原理
说原理之前,在这里说下使用mapStruct的核心原因
与其他映射框架相比,MapStruct在编译时生成bean映射,这确保了高性能,可以提前将问题反馈出来,也使得开发人员可以彻底的错误检查。
编译后PersonConverter会生成一个impl,代码如下
public class PersonConverterImpl implements PersonConverter {
public PersonConverterImpl() {
}
public PersonDTO do2dto(PersonDO person) {
if (person == null) {
return null;
} else {
PersonDTO personDTO = new PersonDTO();
personDTO.setUserName(person.getName());
personDTO.setAge(person.getAge());
if (person.getBirthday() != null) {
personDTO.setBirthday((new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(person.getBirthday()));
}
if (person.getGender() != null) {
personDTO.setGender((Gender)Enum.valueOf(Gender.class, person.getGender()));
}
personDTO.setVersion(person.getVersion());
personDTO.setVersionTitle(this.versionConvert(person.getVersion()));
personDTO.setContent("默认不变");
return personDTO;
}
}
总结
mapStruct即保证了代码的简洁可读性,也保证了代码的性能,可以为开发人员解决在编译时期转换产生的问题。相对比目前环境下的类型转换工具,只有mapStarct做到了。