MapStruct
Mapsturct 是一个通过配置公约的一种代码生成器,它大大简化了Java Bean类型之间的映射的实现,而且类型安全,性能高,使用简单 这时有人会提到为什么不直接用
Spring的BeanUtils
,这里给大家做个简单概述:
如果两个对象之间存在不同字段,则不会对这些字段进行处理
如果两个对象之间字段类型不相同,则会导致类型转换异常
关键性能也比较低
当出现两个字段不一致就会导致复制失败
初步验证
1.引入依赖
<dependency>
<groupId>org.mapstruct</groupId>
<!-- jdk8以下就使用mapstruct -->
<artifactId>mapstruct-jdk8</artifactId>
<version>1.2.0.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-proceSSOr</artifactId>
<version>1.2.0.Final</version>
</dependency>
2.定义mapper
/**
* @Mapper 定义这是一个MapStruct对象属性转换接口,在这个类里面规定转换规则
* 在项目构建时,会自动生成该接口的实现类,这个实现类将实现对象属性值复制
* componentModel 属性,它的值就是当前要使用的依赖注入的环境
*/
@Mapper(componentModel = "Spring")
public interface StudentMapper {
//默认加载方式
StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
/**
* 这个方法就是用于实现对象属性复制的方法
*
* @Mapping 用来定义属性复制规则 source 指定源对象属性 target指定目标对象属性
* @param students 这个参数就是源对象,也就是需要被复制的对象
* @return 返回的是目标对象,就是最终的结果对象
*/
@Mappings({
@Mapping(source = "address", target = "addr")
})
StudentsVO students2StudentsVO(Students students);
}
3.验证
Students students3 = new Students("一安未来3","北京",Arrays.asList(1, 2, 3));
StudentsVO studentsVO3 = StudentMapper.INSTANCE.students2StudentsVO(students3);
System.out.println("MapStruct:"+studentsVO3);
List<String> ids = studentsVO3.getIds();
for (String id:ids){
System.out.println(id);
}
//运行
MapStruct:StudentsVO(name=一安未来3, addr=北京, ids=[1, 2, 3])
1
2
3
绑定多个对象的属性值
1.复制实体类Students--->Students2
2.定义mapper
/**
* @Mapper 定义这是一个MapStruct对象属性转换接口,在这个类里面规定转换规则
* 在项目构建时,会自动生成该接口的实现类,这个实现类将实现对象属性值复制
* componentModel 属性,它的值就是当前要使用的依赖注入的环境
*/
@Mapper(componentModel = "spring")
public interface StudentMapper {
//默认加载方式
StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
/**
* 这个方法就是用于实现对象属性复制的方法
*
* @Mapping 用来定义属性复制规则 source 指定源对象属性 target指定目标对象属性
* @param students 这个参数就是源对象,也就是需要被复制的对象
* @return 返回的是目标对象,就是最终的结果对象
*/
@Mappings({
@Mapping(source = "address", target = "addr")
})
StudentsVO students2StudentsVO(Students students);
@Mappings({
@Mapping(source = "students.name", target = "name"),
@Mapping(source = "students.address", target = "addr"),
@Mapping(source = "students2.ids", target = "ids")
})
StudentsVO students2StudentsVO(Students students,Students2 students2);
}
3.验证
Students students = new Students("一安未来3","北京",Arrays.asList(1, 2, 3));
Students2 students2 = new Students2("一安未来3","北京",Arrays.asList(3, 4, 5));
StudentsVO studentsVO3 = StudentMapper.INSTANCE.students2StudentsVO(students,students2);
System.out.println("MapStruct:"+studentsVO3);
//运行
MapStruct:StudentsVO(name=一安未来3, addr=北京, ids=[3, 4, 5])
参数作为属性值
1.定义mapper
/**
* @Mapper 定义这是一个MapStruct对象属性转换接口,在这个类里面规定转换规则
* 在项目构建时,会自动生成该接口的实现类,这个实现类将实现对象属性值复制
* componentModel 属性,它的值就是当前要使用的依赖注入的环境
*/
@Mapper(componentModel = "spring")
public interface StudentMapper {
//默认加载方式
StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
/**
* 这个方法就是用于实现对象属性复制的方法
*
* @Mapping 用来定义属性复制规则 source 指定源对象属性 target指定目标对象属性
* @param students 这个参数就是源对象,也就是需要被复制的对象
* @return 返回的是目标对象,就是最终的结果对象
*/
@Mappings({
@Mapping(source = "address", target = "addr")
})
StudentsVO students2StudentsVO(Students students);
@Mappings({
@Mapping(source = "students.name", target = "name"),
@Mapping(source = "students.address", target = "addr"),
@Mapping(source = "students2.ids", target = "ids")
})
StudentsVO students2StudentsVO(Students students,Students2 students2);
@Mappings({
@Mapping(source = "students.name", target = "name"),
@Mapping(source = "students.address", target = "addr"),
@Mapping(source = "param", target = "ids")
})
StudentsVO students2StudentsVO(Students students, List<String> param);
}
2.验证
Students students = new Students("一安未来3","北京",Arrays.asList(1, 2, 3));
StudentsVO studentsVO3 = StudentMapper.INSTANCE.students2StudentsVO(students,Arrays.asList("5", "6", "7"));
System.out.println("MapStruct:"+studentsVO3);
//运行
MapStruct:StudentsVO(name=一安未来3, addr=北京, ids=[5, 6, 7])
自定义类型转换
1.Students和StudentsVO增加gender字段:Students中为Integer类型 ,StudentsVO中为String类型
2.定义转换类
@Named("genderToString")
public class GenderToString {
public String toStr(Integer gender) {
if (gender==0) {
return "Y";
} else {
return "N";
}
}
public Integer toInt(String gender) {
if ("Y".equals(gender)) {
return 0;
} else {
return 1;
}
}
}
3.定义mapper
/**
* @Mapper 定义这是一个MapStruct对象属性转换接口,在这个类里面规定转换规则
* 在项目构建时,会自动生成改接口的实现类,这个实现类将实现对象属性值复制
* componentModel 属性,它的值就是当前要使用的依赖注入的环境
* 注意当componentModel为spring时,GenderToString也需要交给spring管理
* uses属性支持设置多个
*/
@Mapper(uses = { GenderToString.class})
public interface StudentMapper {
StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
/**
* 这个方法就是用于实现对象属性复制的方法
*
* @Mapping 用来定义属性复制规则 source 指定源对象属性 target指定目标对象属性
* qualifiedByName指明转换类
* @param students 这个参数就是源对象,也就是需要被复制的对象
* @return 返回的是目标对象,就是最终的结果对象
*/
@Mappings({
@Mapping(source = "address", target = "addr"),
@Mapping(source = "gender", target = "gender",qualifiedByName= {"genderToString"})
})
StudentsVO students2StudentsVO(Students students);
@Mappings({
@Mapping(source = "students.name", target = "name"),
@Mapping(source = "students.address", target = "addr"),
@Mapping(source = "students2.ids", target = "ids")
})
StudentsVO students2StudentsVO(Students students,Students2 students2);
@Mappings({
@Mapping(source = "students.name", target = "name"),
@Mapping(source = "students.address", target = "addr"),
@Mapping(source = "param", target = "ids")
})
StudentsVO students2StudentsVO(Students students, List<String> param);
}
4.验证
Students students = new Students("一安未来3",0,"北京",Arrays.asList(1, 2, 3));
StudentsVO studentsVO3 = StudentMapper.INSTANCE.students2StudentsVO(students);
System.out.println("MapStruct:"+studentsVO3);
//运行
MapStruct:StudentsVO(name=一安未来3, gender=Y, addr=北京, ids=[1, 2, 3])
总结
Mapping源码中还有很多属性,比如支持日期格式化dateFormat
,数字格式化numberFormat
等操作
public @interface Mapping {
String target();
String source() default "";
String dateFormat() default "";
String numberFormat() default "";
String constant() default "";
String expression() default "";
boolean ignore() default false;
Class<? extends Annotation>[] qualifiedBy() default {};
String[] qualifiedByName() default {};
Class<?> resultType() default void.class;
String[] dependsOn() default {};
String defaultValue() default "";
}