业务代码的救星——Java对象转换框架MapStruct
介绍
在业务项目的开发中,我们经常需要将Java对象进行转换,比如从外部HSF服务得到的对象转换为本域的业务对象domain object,将domain object转为数据持久层的data object,将domain object 转换为DTO以便返回给外部调用方等。在转换时大部分属性都是相同的,只有少部分的不同,如果手工编写转换代码,会很繁琐。这时我们可以通过一些对象转换框架来更方便的做这件事情。
这样的对象转换框架有不少,比较有名的有ModelMapper和MapStruct。它们所使用的实现技术不同,ModelMapper是基于反射的,通过反射来查找实体对象的字段,并读取或写入值,这样的方式实现原理简单,但性能很差。与ModelMapper框架不同的是,MapStruct是基于编译阶段代码生成的,生成的转换代码在运行的时候跟一般的代码一样,没有额外的性能损失。本文重点介绍MapStruct。
原理
使用方法
1. Mapper声明
通过类似下面的代码声明一个Mapper,MapStruct会在编译时自动生成实现代码。除了基本的功能外,MapStruct提供很多高级的功能,全面支持业务中可能出现各种映射要求。示例代码如下
简要说明如下
1 - 用Mapper注解标注Mapper接口(也可以是抽象类)
2 - 可以调用其他的Mapper,来转换复杂类型的字段
3 - 可以指定一个Decorator类对Mapper实现做定制
4 - 常用的practice:声明一个静态的INSTANCE,便于调用方引用
5 - 同名的字段会自动映射,不同名的通过Mapping注解指定映射关系和映射方法
6 - 嵌套对象映射,映射到字段的成员,或成员的成员等
7 - 通过源类型和目标类型不能确定mapper的情况下,可以给mapping方法命名,在使用的时候指定特定名字的mapping方法
8 - 用constant来指定映射为一个常量值
9 - 用@MappingTarget注解指定update方法的参数中代表目标对象的参数
10 - 通过@InheritConfiguration重用映射配置,避免重复配置
上面这些特性,1,4,5,9是基本功能,使用时候一般都会用到,其他的是相对高级些的功能,可根据需要选用。MapStruct还支持列表映射,等等更多功能,不一一列举。可以参考文末的参考文档 MapStruct Reference Guide。
另外,MapStruct提供IDE插件,能够在编写映射的时候提供辅助,比如自动代码提示,重构辅助等。
2. 调用Mapper
代码如下
3. 整合进Maven
添加dependency
为Maven compile plugin设置annotation processor
4. 整合进IDE
Enable annotation processor
安装插件
使用MapStruct,有一个缺点就是,当属性改名的时候,因为在Mapper上注解中配置的名字,是在字符串里面,是不会自动同步的。但是MapStruct提供了插件来做到这一点,同时还提供代码自动提示,跳转到实现等功能。关于插件的更多信息,见 MapStruct support for IntelliJ IDEA
5. Trouble Shooting
- 找不到注释处理程序:在pom.xml中增加mapstruct-processor的依赖
- 没有找到实现类:在pom.xml中加入对mapstruct-processor的依赖
- 在IDEA里面enable Annotation Processor
- 使用Lombok的情况下,编译时报Data类的setter/getter找不到:把lombok加入到annotationProcessorPath,如下图
参考资料
MapStruct实体间转换快速入门
https://blog.csdn.net/lx_yoyo/article/details/75061614
JDK IO 2017 - Thomas Much - Easy Bean Mappings with MapStruct 1.2
https://www.youtube.com/watch?v=kKK9SczGa3I
MapStruct 1.2.0.Final Reference Guide
http://mapstruct.org/documentation/stable/reference/html
JAVA Annotation Processing技术——Lombok & MapStruct 介绍与使用
https://www.atatech.org/articles/45619
是时候去掉set/get了---浅谈data mapping技术
https://www.atatech.org/articles/45456
Lombok/Mapstruct problem: Cannot find symbol #1270
https://github.com/mapstruct/mapstruct/issues/1270
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
struts2 常用标签总结
1. 使用Struts2的常用逻辑标签 1.1 property标签 功能说明 获取对象的属性值,目标对象默认位于ValueStack栈顶 标签属性 名称 必选 类型 说明 value no Object 对象的属性名称,默认直接输出 ValueStack 栈顶对象 default no String 默认值,如果 value 为 null 则输出此值 escape no Boolean 是否进行html 转义,默认为 true escapeJavaScript no Boolean 是否进行JavaScript 转义,默认为 false eg: <s:property value="user.userName"/> 1.2 if-elseif-else标签 功能说明: 替代Java语法中的if/else 标签属性: 名称 必选 类型 说明 test yes Boolean 表达式,决定是否显示if/else if 标签体的内容 eg: 欢迎${user.name} , <s:if test="user.role == 'admin'">系统管理员</s:...
- 下一篇
解构反应式编程——Java 8, RxJava, Reactor之比较
如果你熟悉Java 8,同时又了解反应式编程(Reactive Programming)框架,例如RxJava和Reactor等,你可能会问: “如果我可以用Java 8 的Stream, CompletableFuture, 以及Optional完成同样的事情,为什么还要用RxJava 或者 Reactor呢?” 问题在于,大多数时候你在处理的是简单的任务,这个时候你确实不需要那些反应式编程的库。但是,当系统越来越复杂,或者你处理的本身就是个复杂的任务,你恐怕就得写一些让自己头皮发麻的代码。随着时间的推移,这些代码会变得越来越复杂和难以维护。 RxJava和Reactor提供了很多非常趁手的功能,能够支持你在未来更轻松地维护你的代码,实现新需求。但是这个优势到底有多大,具体体现在哪些方面?没有标准无法比较,让我们定义8个比较的维度,来帮助我们理解Java 8的API以及反应式编程的库之间的差别。 Composable(可组装) Lazy(延迟执行) Reusable(可重用) Asynchronous(异步) Cacheable(可缓存) Push or Pull(推还是拉) Bac...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS8安装Docker,最新的服务器搭配容器使用
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- 设置Eclipse缩进为4个空格,增强代码规范
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8编译安装MySQL8.0.19
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Hadoop3单机部署,实现最简伪集群