pom 配置:
1 | <properties> |
关于lombok和mapstruct的版本兼容问题,maven插件要使用3.6.0版本以上、lombok使用1.16.16版本以上,另外编译的lombok mapstruct的插件不要忘了。否则会出现下面的错误:No property named “aaa” exists in source parameter(s). Did you mean “null”?
这种异常就是lombok编译异常导致缺少get setter方法造成的。还有就是缺少构造函数也会抛异常。
1 |
|
实体类是开发过程少不了的,就算是用工具生成肯定也是要有的,需要手写的部分就是这个Mapper的接口,编译完成后会自动生成相应的实现类
然后就可以直接用mapper进行实体的转换了
1 | public class Test { |
mapper可以进行字段映射,改变字段类型,指定格式化的方式,包括一些日期的默认处理。
可以手动指定格式化的方法:
1 |
|
上面只是最简单的实体映射处理,下面介绍一些高级用法
List 转换
属性映射基于上面的mapping配置
1 |
|
多对象转换到一个对象
1 |
|
默认值
1 |
|
转换基类
准备工作
使用常见的 User 类以及对应 UserDto 对象来演示。
1 |
|
注意观察这两个类的区别。
因为项目中的对象转换操作基本都一样,因此抽取除了一个转换基类,不同对象如果只是简单转换可以直接继承该基类,而无需覆写基类任何方法,即只需要一个空类即可。
如果子类覆写了基类的方法,则基类上的 @Mapping
会失效。
1 |
|
实现 User 与 UserVo 对象的转换器
1 | import org.mapstruct.Mapper; |
这里使用的是 Spring 的方式,@Mapper
注解的 componentModel 属性值为 spring,不过应该大多数都用的此模式进行开发。
@Mapping
用于配置对象的映射关系,示例中 User 对象性别属性名为 sex,而UserVo对象性别属性名为gender,因此需要配置 target 与 source 属性。
password 字段不应该返回到前台,可以采取两种方式不进行转换,第一种就是在vo对象中不出现password字段,第二种就是在@Mapping
中设置该字段 ignore = true
。
MapStruct 提供了时间格式化的属性 dataFormat
,支持Date
、LocalDate
、LocalDateTime
等时间类型与String的转换。
示例中birthday 属性为 LocalDate 类型,可以无需指定dataFormat自动完成转换,而LocalDateTime
类型默认使用的是ISO格式时间,在国内往往不符合需求,因此需要手动指定一下 dataFormat。
自定义属性类型转换方法
一般常用的类型字段转换 MapStruct都能完成,但是有一些是自定义的对象类型,MapStruct就不能进行字段转换,这就需要编写对应的类型转换方法,这里使用的是JDK8,支持接口中的默认方法,可以直接在转换器中添加自定义类型转换方法。
示例中User对象的config属性是一个JSON字符串,UserVo对象中是List类型的,这需要实现JSON字符串与对象的互转。
1 | default List<UserConfig> strConfigToListUserConfig(String config) { |
如果是 JDK8以下的,不支持默认方法,可以另外定义一个 转换器,然后再当前转换器的 @Mapper
中通过 uses = XXX.class
进行引用。
定义好方法之后,MapStruct当匹配到合适类型的字段时,会调用自定义的转换方法进行转换。
单元测试
1 | 4j |
常见问题
当两个对象属性不一致时,比如User对象中某个字段不存在与UserVo当中时,在编译时会有警告提示,可以在@Mapping
中配置 ignore = true
,当字段较多时,可以直接在@Mapper
中设置unmappedTargetPolicy
属性或者unmappedSourcePolicy
属性为 ReportingPolicy.IGNORE
即可。
如果项目中也同时使用到了 Lombok,一定要注意 Lombok的版本要等于或者高于1.18.10,否则会有编译不通过的情况发生。