mapStruct学习笔记
mapStruct是一个专门进行数据类型转化工具,与ModelMapper和BeanUtils的反射不同,这个MapStruct抛弃了动态生成的策略,反而采用了类似代理的方式,编译的时候进行动态生成,也就是说在编译的时候,就把要我们需要的get、set都已经写到了“代理类”的class文件里了。然后代码运行的时候,直接使用的是代理类。大概得过程mapstruct根据一般的规范定义一套解析规则,然后开发人员按规则去写,然后编译的时候,mapstruct按这个规则生成一个类,这个类里包含了实体转化的各种set、get方法。
通过编译,我们可以找到这个代理生成的类。
mapstruct整合SpringBoot
导入maven依赖,这里的版本号采用用的比较多的1.3.1.Final
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</dependency>
定义接口(这里先留个疑问,为啥要定义接口)
注意:我们为了方便找到要映射的实体和业务模块,因此我们把映射的接口写到业务实体包里。接口的命名与映射的实体保持一致,仅在接口的命名最后添加Mapper即可。
接口的定义采用以业务为导向,比如request2Dto,表示从web层转化到Service层。使用这一个方法即可。没有必须请不要定义多余的接口。
mapStruct的使用
SearchDto dto = SearchAdvanceRequestMapper.INSTANCE.request2Dto(searchAdvanceRequest);
mapStruct异名字段映射
异名字段的映射需要在接口的转化接口中指定来源实体的字段和目标实体的字段信息。这里使用`@Mapping`注解把uid转换到dto中的userId字段
@Mapper
public interface SearchAdvanceRequestMapper {
/**
* 映射实体
*/
SearchAdvanceRequestMapper INSTANCE = Mappers.getMapper(SearchAdvanceRequestMapper.class);
/***
* 数据转化
* @param request 请求
* @return dto
*/
@Mapping(source = "uid", target = "userId")
SearchDto request2Dto(SearchAdvanceRequest request);
}
mapStruct虚方法自定义
注意:这里的虚方法是java8的特性。
如果采用自定义的话,就直接用自定义了。所以我们将自定义的mapstruct最后用在小部分数据上。
这里把小部分的数据中的request的实体转换成dto中的ageDto属性,并对属性进行改变。这里把int转化为了string类型
@Mapping(source = "uid", target = "userId")
@Mapping(source = "request", target = "age")
SearchDto request2Dto(SearchAdvanceRequest request);
default AgeDto request2Dto1(SearchOrdinaryRequest request) {
AgeDto dto = new AgeDto();
dto.setAge(String.valueOf(request.getAge()));
return dto;
}
mapStruct多转一
有些时候,我们需要将多个实体转化到一个实体中去。就是说我们传入两个实体,然后转化的结果是一个实体。
@Mapper
public interface UserModifyRequestMapper {
/**
* 映射实体
*/
UserModifyRequestMapper INSTANCE = Mappers.getMapper(UserModifyRequestMapper.class);
/**
* 多对一测试
* @param request request
* @param userPasswordRequest passwrod
* @return dto
*/
@Mapping(source = "request.userAge", target = "age")
@Mapping(source = "userPasswordRequest.password", target = "userPassword")
UserDto request2Dto(UserAddRequest request, UserPasswordRequest userPasswordRequest);
}
Mappers.getMapper(A.class)解析
这个类主要就是通过类加载器,加载所有的类,然后选择以传入类名+impl结尾的类。所以返回都是mapStruct生成的实现类,如文章第一图一样的impl类。
private static <T> T doGetMapper(Class<T> clazz, ClassLoader classLoader) throws NoSuchMethodException {
try {
Class<T> implementation = classLoader.loadClass(clazz.getName() + "Impl");
Constructor<T> constructor = implementation.getDeclaredConstructor();
constructor.setAccessible(true);
return constructor.newInstance();
} catch (ClassNotFoundException var4) {
return getMapperFromServiceLoader(clazz, classLoader);
} catch (InvocationTargetException | IllegalAccessException | InstantiationException var5) {
throw new RuntimeException(var5);
}
}
mapStruct实现机制探索
mapStruct采用java的apt(注解解析器)来实现的,也就是要继承AbstractProcessor类,然后重写init和process方法,当然process方法的参数就是包含了所有注解的类,然后在process中进行处理。这里先解析,然后重新write到目录去了。也就是上边说的impl后缀的目标文件。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 使用Kustomize定制Helm Chart
- 踩坑了,JDK8 中 HashMap 依然会产生死循环问题!
- 使用shell-operator实现Operator
- 教你用Python 操作 PDF 的几种方法
- 如何在K8s上设置生产级的EFK?(上)
- IntelliJ IDEA 构建 Maven 多模块工程项目
- GDP越高就越幸福吗?用Python分析《世界幸福指数报告》后我们发现…
- 图解:什么是哈希?
- 【Python基础】一文看懂 Pandas 中的透视表
- 彻底干掉恶心的 SQL 注入漏洞, 一网打尽!
- 某小型公司持续集成工具 Jenkins 实践
- 使用RBAC Impersonation简化Kubernetes资源访问控制
- 求求你别再用 MySQL offset 和 limit 分页了?
- 短视频带货源码,获取购物车中所有商品列表并加载显示
- 【Flutter 实战】菜单(Menu)功能