我们开发过程中会遇到很多bean拷贝得过程,最简单粗暴得方法就是set/get方法,当然这也是最愚蠢得方法,代码显得过于冗长和笨重,其次还有框架BeanUtils在使用反射的时候都会影响到性能。虽然我们可以进行反射信息的缓存来提高性能。但是像这种的话,需要类型和名称都一样才会进行映射,有很多时候,由于不同的团队之间使用的名词不一样,还是需要很多的手动 set/get 等功能。
MapStruct 就解决了这些问题带来的困扰,它是一个生成类型安全,高性能且无依赖的 JavaBean 映射代码的注解处理器(annotation processor)
性能高
这是相对反射来说的,反射需要去读取字节码的内容,花销会比较大。而通过 MapStruct 来生成的代码,其类似于人手写。速度上可以得到保证。
使用简单
如果是完全映射的,使用起来肯定没有反射简单。用类似 BeanUtils 这些工具一条语句就搞定了。但是,如果需要进行特殊的匹配(特殊类型转换,多对一转换等),其相对来说也是比较简单的。
基本上,使用的时候,我们只需要声明一个接口,接口下写对应的方法,就可以使用了。当然,如果有特殊情况,是需要额外处理的。
代码独立
生成的代码是对立的,没有运行时的依赖。
易于 debug
在我们生成的代码中,我们可以轻易的进行 debug。
pom引入
org.mapstruct
mapstruct
1.4.2.Final
org.mapstruct
mapstruct-jdk8
1.4.2.Final
org.mapstruct
mapstruct-processor
1.4.2.Final
实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student implements Serializable {
/**
* id
*/
private Integer id;
/**
* 学生姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 性别
*/
private String sex;
}
准备VO类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class StudentRequestVo {
/**
* id
*/
private Integer studentId;
/**
* 学生姓名
*/
private String studentName;
/**
* 年龄
*/
private Integer studentAge;
}
定义转换器
//这个注解是MapStruct得注解,不是mybatis注解
@Mapper(componentModel = "spring", injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public interface StudentMapStrut {
@Mappings({
@Mapping(target = "id",source = "studentId"),
@Mapping(target = "name",source = "studentName"),
@Mapping(target = "age",source = "studentAge")
})
Student studentConvert(StudentRequestVo studentRequestVo);
}
使用
Student student = studentMapStrut.studentConvert(new StudentRequestVo(1, "张三", 15));
@Mapper(componentModel = "spring", injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public interface StudentMapStrut {
@Mappings({
@Mapping(target = "id",source = "studentId"),
@Mapping(target = "name",source = "studentName"),
@Mapping(target = "age",source = "studentAge")
})
Student studentConvert(StudentRequestVo studentRequestVo);
List studentListConvert(List studentRequestVos);
}
//老师学生vo
@Data
@NoArgsConstructor
@AllArgsConstructor
public class StudentAndTeacher implements Serializable {
/**
* id
*/
private Integer id;
/**
* 学生姓名
*/
private String studentName;
/**
* 老师姓名
*/
private String teacherName;
}
//学生vo
@Data
@NoArgsConstructor
@AllArgsConstructor
public class StudentRequestVo {
/**
* id
*/
private Integer studentId;
/**
* 学生姓名
*/
private String studentName;
/**
* 年龄
*/
private Integer studentAge;
}
//老师vo
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TeacherRequestVo {
/**
* id
*/
private Integer teacherId;
/**
* 学生姓名
*/
private String teacherName;
/**
* 年龄
*/
private Integer teacherAge;
}
映射成一个对象
@Mappings({
@Mapping(target = "studentName",source = "studentRequestVo.studentName"),
@Mapping(target = "teacherName",source = "teacherRequestVo.teacherName")
})
StudentAndTeacher studentAndTeacherConvert(StudentRequestVo studentRequestVo,TeacherRequestVo teacherRequestVo);
以对象转换为例,我们想把年龄20岁以下的,统一存储为0,20岁以上的统一存储为1.
@Mappings({
@Mapping(target = "id",source = "studentId"),
@Mapping(target = "name",source = "studentName"),
@Mapping(target = "age",expression = "java(com.example.demo.mapstrut.MapStructUtil.ageConvert(studentRequestVo.getStudentAge()))")
})
Student studentConvert(StudentRequestVo studentRequestVo);
public class MapStructUtil {
public static Integer ageConvert(Integer studentAge){
if (studentAge<=20){
return 0;
}else {
return 1;
}
}
}
4.总结:
mapstruct还有很多功能,例如dateFormat 、numberFormat 实现自定义转换,平时使用基本可以参考本文。如需更详细了解可参考官网: https://mapstruct.org/documentation/stable/reference/html/
关注我的微信公众号