1、简介
mapstruct是一种实体类映射框架,通过Java注解将一个实体类的属性安全地赋值给另一个实体类。
实体类映射框架大致有两种:
1、运行期通过java反射机制动态映射;
2、编译期动态生成getter/setter,在运行期直接调用框架编译好的class类实现实体映射。
mapstruct属于第2种,相比运行期的映射框架有以下优点:
安全性高:编译期就实现源对象到目标对象的映射, 如果编译期能够通过,运行期就不会报错。
速度快:运行期间直接调用实现类的方法,不需要在运行期间使用反射进行转化。
2、原理
mapstruct基于JSR 269实现,JSR 269是JDK引进的一种规范。有了它,能够实现在编译期处理注解,并且读取、修改和添加抽象语法树中的内容。JSR 269使用Annotation Processor在编译期间处理注解,Annotation Processor相当于编译器的一种插件,因此又称为插入式注解处理。想要实现JSR 269,主要有以下步骤:
1、继承AbstractProcessor类,重写process方法,在process方法中实现自己的注解处理逻辑。
2、在META-INF/services目录下创建javax.annotation.processing.Processor文件注册自己实现的Annotation Processor
()、java编译过程:源代码---编译器--->.class文件---JVM--->二进制码
()、mapstruct编译过程:在源代码-->.class文件步骤中完成
3、使用
3.1 添加依赖
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.2.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.2.Final</version>
</dependency>
3.2 创建convert接口
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import java.util.List;
//一般只需要加注解@Mapper,imports赋值时间
@Mapper(imports = LocalDateTime.class)
public interface TestConvert {
TestConvert INSTANCE = Mappers.getMapper(testConvert.class);
//两个类字段完全一致时不需要注解@Mappings
@Mappings({
//把来源类的param1字段值赋给目标类的param11字段
@Mapping(source = "param1", target = "param11"),
//来源类的日期字段转成指定格式的目标类字符串字段
@Mapping(source = "createTime", target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss"),
//目标类的id不需要映射
@Mapping(target = "id", ignore = true),
//expression+imports,赋值当前时间给目标类字段modifyTime
@Mapping(target = "modifyTime", expression = "java(java.time.LocalDateTime.now())")
})
TargetDTO sourceToTarget(SourceDTO source);
//转换list必须先转换单个类,方法名一致
List<TargetDTO> sourceToTarget(List<SourceDTO> sourceList);
TargetDTO2 sourceToTarget2(SourceDTO2 source);
List<TargetDTO2> sourceToTarget2(List<SourceDTO2> sourceList);
}
4、注意
4.1 convert接口内容更新后,需要clean、package使更新生效
4.2 mapstruct依赖引入建议放在<dependencies></dependencies>标签末尾位置,避免和lombok冲突