大家好,我是一安,之前听码友说MapStruct做Java之间Bena对象转换,那是相当舒服。
今天有时间,特意尝试了一下,确实不错,值得推荐。
MapStruct
Mapsturct 是一个通过配置公约的一种代码生成器,它大大简化了Java Bean类型之间的映射的实现,而且类型安全,性能高,使用简单
这时有人会提到为什么不直接用Spring的BeanUtils
,这里给大家做个简单概述:
针对1和2,举个例子
@Data
@AllArgsConstructor
public class Students {
private String name;
private String address;
private List<Integer> ids;
}
@Data
public class StudentsVO {
private String name;
private String addr;
private List<String> ids;
}
可以看出两个实体类,address和addr字段名不一致,ids里字段类型不一致
,下面代码验证一下:
Students students2 = new Students("一安未来2","北京", Arrays.asList(1, 2, 3));
StudentsVO studentsVO2 = new StudentsVO();
BeanUtils.copyProperties(students2, studentsVO2);
System.out.println("BeanUtils:"+studentsVO2);
List<String> ids = studentsVO2.getIds();
for (String id:ids){
System.out.println(id);
}
//运行结果
BeanUtils:StudentsVO(name=一安未来2, addr=null, ids=[1, 2, 3])
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at com.capitek.mapstruct.Test.main(Test.java:26)
但是Mapsturct却可以很好的处理以上问题,而且性能也优于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 "";
}
号外!号外!
如果这篇文章对你有所帮助,或者有所启发的话,帮忙点赞、在看、转发、收藏,你的支持就是我坚持下去的最大动力!
原文始发于微信公众号(一安未来):MapStruct 高效-安全-优雅实现Bean转换
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/44855.html