Mapstruct使用介绍
一:使用背景
我们在读库之后(po->dto),返回前端数据(dto->vo)的需要转换函数,这时候我们一般会有以下几种方式
1:手动编写convert函数
2:利用反射工具进行映射(spring的BeanUtils, fastjson的JSON.parseObject)
3:利用工具生成convert函数(Mapstruct)
个人比较偏好Mapstruct,手动写convert函数比较繁琐,而且很多转换的过程中属性名和属性类型都是相同的。
反射工具进行映射的性能无法保证,也可能出现问题(比如fastjson已经被人在社区中提出bug)。
二:使用姿势
实例一(字段完全相同)
1:在pom.xml中引入依赖。
<dependency>
<groupid>junit</groupid>
<artifactid>junit</artifactid>
<version>4.11</version>
<scope>test</scope>
</dependency>
<plugin>
<groupid>org.apache.maven.plugins</groupid>
<artifactid>maven-compiler-plugin</artifactid>
<version>3.5.1</version>
<configuration>
<source>1.8
<target>1.8</target>
<annotationprocessorpaths>
<path>
<groupid>org.mapstruct</groupid>
<artifactid>mapstruct-processor</artifactid>
<version>1.3.0.Beta2</version>
</path>
</annotationprocessorpaths>
</configuration>
</plugin>
2:编写要转换的两个实体类
package controller;
/**
* @date: 2019/10/24
* @description: SimpleSource
*/
public class SimpleSource {
private String name;
private String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
package controller;
/**
* @date: 2019/10/24
* @description: SimpleDestination
*/
public class SimpleDestination {
private String name;
private String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
3:编写要映射的Mapper接口
package controller;
import org.mapstruct.Mapper;
@Mapper
public interface SimpleSourceDestinationMapper {
SimpleDestination sourceToDestination(SimpleSource source);
SimpleSource destinationToSource(SimpleDestination destination);
}
4:mvn clean install生成要转换的convert函数(生成的代码在target文件夹下)
5:生成代码
package controller;
import javax.annotation.Generated;
public class SimpleSourceDestinationMapperImpl implements SimpleSourceDestinationMapper {
@Override
public SimpleDestination sourceToDestination(SimpleSource source) {
if ( source == null ) {
return null;
}
SimpleDestination simpleDestination = new SimpleDestination();
simpleDestination.setName( source.getName() );
simpleDestination.setDescription( source.getDescription() );
return simpleDestination;
}
@Override
public SimpleSource destinationToSource(SimpleDestination destination) {
if ( destination == null ) {
return null;
}
SimpleSource simpleSource = new SimpleSource();
simpleSource.setName( destination.getName() );
simpleSource.setDescription( destination.getDescription() );
return simpleSource;
}
}
实例二(字段有差异)
1:编写要转换的两个实体类
package controller;
/**
* @date: 2019/10/24
* @description: Person实体类
*/
public class Person {
private String name;
private String sex;
private Integer age;
private String tall;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getTall() {
return tall;
}
public void setTall(String tall) {
this.tall = tall;
}
}
package controller;
/**
* @date: 2019/10/24
* @description: 学生实体类
*/
public class Student {
private String name;
private String sex;
private Integer age;
private Long height;
private Integer rank;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Long getHeight() {
return height;
}
public void setHeight(Long height) {
this.height = height;
}
public Integer getRank() {
return rank;
}
public void setRank(Integer rank) {
this.rank = rank;
}
}
2:编写要映射的Mapper接口()
package controller;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
@Mapper
public interface PersonMapper
{
@Mappings({
@Mapping(source = "tall", target = "height"),
})
Student personToStudent(Person person);
}
3:生成的Mapper实现类的位置
4:生成的代码
package controller;
import javax.annotation.Generated;
public class PersonMapperImpl implements PersonMapper {
@Override
public Student personToStudent(Person person) {
if ( person == null ) {
return null;
}
Student student = new Student();
if ( person.getTall() != null ) {
student.setHeight( Long.parseLong( person.getTall() ) );
}
student.setName( person.getName() );
student.setSex( person.getSex() );
student.setAge( person.getAge() );
return student;
}
}
三:注意事项
1:要映射的源实体类和目的实体类要写setter
2:要映射的源实体类和目的实体类不要写全参数的构造函数(否则未自动映射的字段并且未处理的字段会有问题)。