1 啥玩意?
MapStruct 是一个代码生成器,它基于约定优于配置的方法极大地简化了 Java bean 类型之间映射的实现。
生成的映射代码使用简单的方法调用,因此速度快、类型安全且易于理解。
2 为什么?
多层应用程序通常要在不同对象模型(如entities和 DTO)之间映射。编写映射代码是乏味易出错任务。 MapStruct 旨在通过尽可能自动化来简化这项工作。
与其他映射框架相比,MapStruct 在编译时生成 bean 映射,这确保高性能,允许快速的开发人员反馈和彻底的错误检查。
3 如何?
MapStruct 是一个注解处理器,它插入到 Java 编译器中,可以在命令行构建(Maven、Gradle 等)以及IDE中使用。
MapStruct 使用合理的默认值,但在配置或实现特殊行为时会妨碍。
4 快速上手
下面演示如何使用 MapStruct 映射两个对象。
4.1 你的两个类
假设我们有一个代表文章的类(例如 JPA 实体)和一个附带的数据传输对象 (DTO):
public class InterviewEntity implements Serializable {
/**
* 主键
*/
@TableId
private Long id;
/**
*
*/
private Long userId;
/**
*
*/
private String title;
/**
*
*/
private String newTitle;
/**
*
*/
private String content;
/**
*
*/
private String newContent;
/**
*
*/
private String type;
/**
*
*/
private String status;
/**
*
*/
private String hasEdit;
/**
*
*/
private Integer isAnonymousFlag;
private Integer jobId;
// 面经分类
@TableField(exist = false)
private String careerName;
/**
*
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createAt;
/**
*
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date editTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
private Integer pageView;
}
@Data
public class ArticleVO {
/**
* 主键
*/
private String id;
/**
* 用户主键
*/
private Long userId;
/**
* 标题
*/
private String title;
/**
* 内容
*/
private String content;
/**
* 创建时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createAt;
/**
* 职业主键
*/
private Integer jobId;
/**
* 文字类型
*/
private Integer contentType;
/**
* 职业名称
*/
private String careerName;
}
两种类型非常相似,只是座位数属性具有不同的名称,并且 type 属性在 Car 类中是特殊的枚举类型,但在 DTO 中是普通字符串。
4.2 mapper 接口
要生成用于从 Car 对象创建 CarDto 对象的映射器,需定义映射器接口:
package com.javagpt.back.converter;
import com.javagpt.back.entity.InterviewEntity;
import com.javagpt.back.vo.InterviewVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
/**
* @author JavaEdge
* @date 2023/10/24
*/
// @Mapper注解将接口标记为映射接口,并让 MapStruct 处理器在编译时启动
@Mapper
public interface InterviewConverter {
// 可从 Mappers 类中检索接口实现的实例。按约定接口声明一个成员 INSTANCE,为客户端提供访问
InterviewConverter INSTANCE = Mappers.getMapper(InterviewConverter.class);
// 对于src对象和target对象中名称不同的属性,可用@Mapping注解配置名称
@Mapping(source = "numberOfSeats", target = "seatCount")
// 实际的映射方法:期望源对象作为参数,并返回目标对象。方法名自由写
InterviewVO to(InterviewEntity interviewEntity); 2
}
可能的情况下,将为src和taget中具有不同类型的属性执行类型转换,例如type属性将从枚举类型转换为字符串。
当然,一个接口中可以有多种映射方法,所有这些方法都将由 MapStruct 生成一个实现。
4.3 使用映射器
基于映射器接口,客户端可以以非常简单且类型安全的方式执行对象映射:
@Test
public void shouldMapCarToDto() {
CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
}