1、简述
在 Java 开发中,对象之间的转换是一个常见的需求,尤其是在 DTO(数据传输对象)和实体类之间的转换过程中。手动编写转换代码既耗时又容易出错,而 MapStruct 是一个优秀的对象映射框架,可以通过注解生成高效的对象转换代码,从而大大提升开发效率。
样例代码: https://gitee.com/lhdxhl/springboot-example.git
本文将介绍 MapStruct 的基本功能、配置方法,并列出详细的使用示例,帮助开发者快速掌握 MapStruct 的使用。
2、MapStruct 的特点
- 性能高:MapStruct 基于注解生成静态映射代码,性能远优于基于反射的框架。
- 简单易用:只需定义接口或抽象类,无需手写转换逻辑。
- 灵活性强:支持字段名不一致、自定义映射逻辑、集合映射等复杂场景。
- 易于维护:减少样板代码,保持代码清晰简洁。
2.1 添加 Maven 依赖
在使用 MapStruct 之前,需要添加其依赖。以下是 MapStruct 的 Maven 依赖:
<!-- mapstruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
<scope>provided</scope>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.40</version>
<scope>compile</scope>
</dependency>
2.2 配置注解处理器
IntelliJ IDEA:
- 打开 File -> Settings -> Build, Execution, Deployment -> Compiler -> Annotation Processors。
- 勾选 Enable annotation processing。
Eclipse:
- 打开 Window -> Preferences -> Java -> Compiler -> Annotation Processing,启用注解处理器。
3、基础示例
3.1 定义实体类和 DTO
假设我们有以下两个类:
@Data
public class User {
private Long id;
private String name;
private String email;
private Address address;
}
@Data
public class UserDTO {
private Long userId;
private String userName;
private String userEmail;
private String city;
}
@Data
public class Address {
private String city;
private String street;
}
3.2 创建 Mapper 接口
使用 MapStruct 定义一个映射接口:
@Mapper
public interface UserMapper {
// 将 User 转换为 UserDTO
@Mapping(source = "id", target = "userId")
@Mapping(source = "name", target = "userName")
@Mapping(source = "email", target = "userEmail")
@Mapping(source = "address.city", target = "city")
UserDTO userToUserDTO(User user);
// 将 UserDTO 转换为 User
@Mapping(source = "userId", target = "id")
@Mapping(source = "userName", target = "name")
@Mapping(source = "userEmail", target = "email")
@Mapping(target = "address.city", source = "city")
User userDTOToUser(UserDTO userDTO);
}
注意:@Mapping 注解用来处理字段名不一致的情况,source 指来源字段,target 指目标字段。
3.3 使用生成的 Mapper 实例
MapStruct 会自动生成实现类,你可以通过 Mappers.getMapper() 获取实例:
import com.lm.mapstruct.dto.UserDTO;
import com.lm.mapstruct.entry.Address;
import com.lm.mapstruct.entry.User;
import com.lm.mapstruct.mapper.UserMapper;
import org.mapstruct.factory.Mappers;
public class UserExample {
public static void main(String[] args) {
UserMapper mapper = Mappers.getMapper(UserMapper.class);
// 模拟 User 对象
User user = new User();
user.setId(1L);
user.setName("John");
user.setEmail("john@example.com");
Address address = new Address();
address.setCity("New York");
user.setAddress(address);
// 转换为 DTO
UserDTO userDTO = mapper.userToUserDTO(user);
System.out.println("UserDTO: " + userDTO);
// DTO 转换回实体
User newUser = mapper.userDTOToUser(userDTO);
System.out.println("User: " + newUser);
}
}
3.4 自定义映射逻辑
如果某些字段需要特殊处理,可以使用 @Mapping 的 qualifiedByName 指定自定义方法:
@Mapper
public interface UserMapper {
@Mapping(source = "email", target = "userEmail", qualifiedByName = "emailToUppercase")
UserDTO userToUserDTO(User user);
@Named("emailToUppercase")
static String emailToUppercase(String email) {
return email.toUpperCase();
}
}
3.5 字段映射
当源字段为 null 时,可以设置默认值:
@Mapping(source = "name", target = "userName", defaultValue = "Unknown")
如果某些字段不需要映射,可以使用 ignore:
@Mapping(target = "email", ignore = true)
4、总结
MapStruct 是一个高效的对象映射工具,通过简单的注解即可生成高性能的转换代码。在项目中使用 MapStruct,不仅能减少手动编写的冗余代码,还能让代码更加清晰易维护。本文展示了从基本到高级的使用示例,希望能帮助大家快速上手 MapStruct。
如果你在使用 MapStruct 时遇到问题,欢迎在评论区留言讨论!
评论区