这篇文章主要讲解了“如何使用Mapstruct”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何使用Mapstruct”吧!
成都创新互联公司坚持“要么做到,要么别承诺”的工作理念,服务领域包括:成都网站制作、成都网站设计、外贸营销网站建设、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的共和网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!
在Java中,有三种方式来处理这些属性拷贝:
直接硬编码,把代码硬怼上去
使用各种BeanUtils,通过反射完成赋值
使用类似MapStruct的工具,直接在编译期完成
1. 如何使用?
照例,需要在pom中加入依赖包,我们这里用的是1.4.1.Final版本。
org.mapstruct mapstruct ${org.mapstruct.version}
这还没完,还需要在pom中的build部分,增加一个插件。搞这么复杂,是因为它的原理和lombok是一样的,同样通过APT在编译器实现的。
这意味着,它的代码,在编译期就完成了。不需要反射,所以效率就和直接写get、set,是一样的。
org.apache.maven.plugins maven-compiler-plugin 3.8.1 1.8 org.mapstruct mapstruct-processor ${org.mapstruct.version} org.projectlombok lombok 1.18.16 org.projectlombok lombok-mapstruct-binding 0.2.0
这时候,我们就可以使用它提供的注解,方便的进行属性拷贝了。
@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) public interface Transform { Transform T = Mappers.getMapper(Transform.class); Member fromMemberEntity(MemberEntity entity); MemberEntity fromMember(Member member); }
上面是一段示例代码。Mapper注解,标志着这是一个类型转换工具(对象映射器),它提供了很多策略供我们选择。直接写接口文件,并不需要做一些额外的动作,mapstruct就知道你要干什么!
在传统的编程中,如果Member的属性非常的多,我们需要手工完成这个过程,代码会非常的多。
使用Mapperstruct之后,这部分重复的劳动,工具都替我们做了。
瞧瞧下面这张图!
上面的图表明了,代码在target下的generated-source目录下生成,这就是我们上面添加的插件的功劳;代码的内容,其实就是一些非空判断和get、set等。相同字段名相同类型的属性,将会无差别的拷贝过去。
如果你的bean属性非常的多,这个工具会让你的代码由几百行,变成几行!
2. 与其他方式比较
那mapstruct有什么优势么?为什么不直接使用BeanUtils?它们的效果一样的啊,而且后者各种类库都有提供。
主要原因,就是效率问题。
BeanUtils是通过反射实现的,效率肯定很低;而mapstuct是基于APT实现的,没有性能损耗。
BeanUtils的属性拷贝,在判断空值和不同类型的属性时,有很多障碍,会歇菜;而mapstruct有非常灵活的策略和转化方式,自定义性比较强(后面会谈到)。
3. 复杂场景
那下面我们就来看一个复杂的场景。
如果你的bean中,只有一些普通的属性,那么使用mapstruct,就是如丝般的顺滑。但总有一些异常情况,需要使用更高级的处理方式。
假设我想要由Unit转化为ProductUnitEntity,但其中有个字段measureType它们的类型不一样,我们就可以使用Mappings注解完成这个转化。
@Mappings({ @Mapping(source = "measureType.value", target = "measureType") }) ProductUnitEntity fromUnit(Unit v);
编译后的代码如下所示。有了source和target,就可以实现比BeanUtils更加牛x的行为。你甚至可以通过dateFormat做一些日期转化之类的。
其实,上面的measureType是一个枚举类型。如何将普通的类型转化为枚举类型呢?我们只需要提供一个default方法就ok了。mapstruct会判断参数类型和返回值,所以说方法的名称可以是任何合法的值。
default Unit.MeasureType measureTypeIntegerToDomain(Integer value) { for (Unit.MeasureType s : Unit.MeasureType.values()) { if (s.getValue() == value) { return s; } } return null; }
那mapstruct能实现List之间的转化么?也是可以的。下面两行代码,就能够自动的补充for循环,让你的代码更加简洁。
ListfromSkuEntityList(List v); List fromSkuList(List v);
End那么问题来了。
既然这么好的东西,那为什么现在的很多项目,都不用mapstruct,甚至连BeanUtils都不用,直接手工在那里get、set呢?
一种原因是,这些工具会大幅减少代码量。mapstruct+hibernate-validate,一个管转化,另一个管验证,简直就是以代码行数论天下的公司的噩梦。绩效会降低的!
另一种原因就是,使用这些工具,并 不利于项目的重构 。假如你在DTO里把a字段改成了b字段,mapstruct都贴心的为你忽略了这些变化。你的项目代码并不会提示错误,风险将直接带到运行时。
而使用get、set的方式,除了代码量变的非常多以外,唯一的风险就是开发人员忘记了为某个新增的字段赋值。
在这种情况下,机器干的活,并不一定比人类可靠。所以使用mapstruct有一个大的前提:你的团队,能够通过约定,不给变量乱起名字,不乱重构。如此,才能发挥它的价值。
感谢各位的阅读,以上就是“如何使用Mapstruct”的内容了,经过本文的学习后,相信大家对如何使用Mapstruct这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!