Spring Boot中MapStruct的用法
下面通过一个具体的业务场景演示 MapStruct 在 Spring Boot 项目中的完整用法。我们将实现AuditInfoBO业务对象到AuditInfoDTO数据传输对象的转换包括字段映射、嵌套对象、集合处理等常见情况。场景说明假设我们有一个审计日志模块BO 包含了审计记录的基本信息、操作人信息和操作项列表DTO 需要将这些数据返回给前端同时做一些字段调整如字段重命名、状态码转描述。1. 定义 BO 和 DTO 类BO 类业务对象java// AuditInfoBO.java import java.time.LocalDateTime; import java.util.List; public class AuditInfoBO { private Long id; private String action; // 操作动作 private Integer status; // 状态码0-成功1-失败 private LocalDateTime createTime; // 创建时间 private UserBO operator; // 操作人嵌套 private ListAuditItemBO items; // 操作项列表 // 构造器、getter/setter 省略可用 Lombok }java// UserBO.java public class UserBO { private Long userId; private String userName; private String email; // getter/setter }java// AuditItemBO.java public class AuditItemBO { private String itemId; private String itemName; private Integer quantity; // getter/setter }DTO 类数据传输对象java// AuditInfoDTO.java import java.time.LocalDate; import java.util.List; public class AuditInfoDTO { private Long id; private String action; private String statusDesc; // 状态描述由 status 转换而来 private LocalDate createDate; // 仅日期原 createTime 是 LocalDateTime private UserDTO operator; // 操作人嵌套 private ListAuditItemDTO items; // 操作项列表 // getter/setter }java// UserDTO.java public class UserDTO { private Long id; // 字段名与 BO 不同原 userId - id private String name; // 字段名不同原 userName - name private String email; // getter/setter }java// AuditItemDTO.java public class AuditItemDTO { private String itemId; private String itemName; private Integer quantity; // getter/setter }2. 创建 MapStruct Mapper 接口我们将使用Mapper注解并通过componentModel spring将其注册为 Spring Bean。java// AuditInfoMapper.java import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Named; Mapper(componentModel spring) // 生成 Spring Bean public interface AuditInfoMapper { // 基础映射同名属性会自动映射如 id - id, action - action Mapping(source createTime, target createDate, dateFormat yyyy-MM-dd) Mapping(source status, target statusDesc, qualifiedByName statusToDesc) Mapping(source operator, target operator) Mapping(source items, target items) AuditInfoDTO toDto(AuditInfoBO bo); // 处理嵌套对象 UserBO - UserDTO单独定义映射方法MapStruct 会自动调用 Mapping(source userId, target id) Mapping(source userName, target name) UserDTO toUserDto(UserBO userBO); // 处理嵌套集合中的每个元素自动调用下面的方法 AuditItemDTO toItemDto(AuditItemBO itemBO); // 自定义方法将状态码转换为描述 Named(statusToDesc) default String statusToDesc(Integer status) { if (status null) return 未知; switch (status) { case 0: return 成功; case 1: return 失败; default: return 其他; } } }说明Mapping(source createTime, target createDate, dateFormat yyyy-MM-dd)将LocalDateTime格式化为指定格式的字符串如果目标类型是String但这里目标是LocalDateMapStruct 会自动截取日期部分dateFormat用于明确转换格式。Mapping(source status, target statusDesc, qualifiedByName statusToDesc)通过自定义方法statusToDesc将状态码转换为描述。嵌套对象operator和集合items的映射MapStruct 会自动查找类型匹配的映射方法toUserDto和toItemDto无需额外注解。如果字段名完全一致连Mapping都不需要直接自动映射。3. 在 Service 中使用 Mapperjava// AuditService.java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; Service public class AuditService { Autowired private AuditMapper mybatisMapper; // MyBatis 的 Mapper数据库操作 Autowired private AuditInfoMapper mapstructMapper; // MapStruct 的 Mapper对象转换 public AuditInfoDTO getAuditInfo(Long id) { // 1. 从数据库查询 BO由 MyBatis 直接映射为 BO 或 Entity AuditInfoBO bo mybatisMapper.selectAuditInfoBO(id); // 2. 使用 MapStruct 转换为 DTO AuditInfoDTO dto mapstructMapper.toDto(bo); return dto; } public ListAuditInfoDTO getAuditList() { ListAuditInfoBO boList mybatisMapper.selectAll(); // 3. 集合映射MapStruct 会逐个转换 return mapstructMapper.toDtoList(boList); // 需要额外定义 toDtoList 方法 } }为了让集合映射更简洁可以在 Mapper 接口中增加默认方法或直接定义javaMapper(componentModel spring) public interface AuditInfoMapper { // ... 已有的映射方法 ListAuditInfoDTO toDtoList(ListAuditInfoBO boList); }MapStruct 会自动生成实现遍历集合并调用toDto方法。4. 编译后生成的实现类供理解执行mvn clean compile后MapStruct 会在target/generated-sources/annotations下生成一个实现类大致内容如下javaComponent public class AuditInfoMapperImpl implements AuditInfoMapper { Override public AuditInfoDTO toDto(AuditInfoBO bo) { if (bo null) return null; AuditInfoDTO dto new AuditInfoDTO(); dto.setId(bo.getId()); dto.setAction(bo.getAction()); // 处理自定义映射 dto.setCreateDate(bo.getCreateTime().toLocalDate()); // 根据 dateFormat 处理 dto.setStatusDesc(statusToDesc(bo.getStatus())); dto.setOperator(toUserDto(bo.getOperator())); dto.setItems(toItemDtoList(bo.getItems())); return dto; } Override public UserDTO toUserDto(UserBO userBO) { if (userBO null) return null; UserDTO dto new UserDTO(); dto.setId(userBO.getUserId()); dto.setName(userBO.getUserName()); dto.setEmail(userBO.getEmail()); return dto; } Override public AuditItemDTO toItemDto(AuditItemBO itemBO) { // 同名属性直接映射 // ... } Override public ListAuditInfoDTO toDtoList(ListAuditInfoBO boList) { // 循环调用 toDto } }5. 与 BeanUtils.copyProperties 对比特性MapStructBeanUtils.copyProperties类型安全编译期检查字段类型、名称运行时可能抛出异常性能直接调用 getter/setter无反射反射调用性能较低嵌套对象映射自动递归映射需定义嵌套映射方法浅拷贝只复制引用集合映射自动生成循环代码需手动遍历自定义转换表达式、默认方法、自定义类型转换器无法直接实现需转换前/后处理字段名称不一致Mapping明确指定无法自动处理必须手动 set代码可读性映射规则集中在一个接口清晰分散在业务代码中难以追踪6. 注意事项与 MyBatis Mapper 同名问题将 MapStruct 的 Mapper 放在不同包如converter命名用XxxConverter或XxxStructMapper避免混淆。Lombok 配合如果 BO/DTO 使用了 Lombok确保pom.xml中正确配置了lombok-mapstruct-binding否则可能出现属性找不到的错误。复杂映射若需更复杂的类型转换如String转Enum可定义自定义类型转换器Mapper的uses属性。总结通过这个例子可以看出MapStruct 将对象转换逻辑从业务代码中抽离以声明式接口定义映射规则既清晰又高效。在 Spring Boot 项目中搭配componentModel spring可以无缝集成是替代BeanUtils.copyProperties的理想选择。

相关新闻

Kylin V10优盘实战:从FAT32到NTFS的兼容性配置与虚拟机挂载

Kylin V10优盘实战:从FAT32到NTFS的兼容性配置与虚拟机挂载

1. 为什么你的优盘在Kylin V10上“认”不出来? 最近在项目上折腾国产化操作系统,Kylin V10用得越来越顺手,但有个小问题几乎每个新接触的同事都会遇到:优盘插上去没反应。这感觉就像你拿着钥匙,却怎么也打不开自家的门…

2026/5/17 11:37:58 阅读更多 →
深入理解Kubernetes磁盘压力驱逐机制:从默认阈值到自定义配置

深入理解Kubernetes磁盘压力驱逐机制:从默认阈值到自定义配置

深入解析Kubernetes磁盘压力驱逐:从监控原理到实战调优 最近在维护一个中等规模的Kubernetes生产集群时,遇到了一个看似简单却让人困惑的问题:几台工作节点上的Pod频繁被驱逐,节点状态显示node.kubernetes.io/disk-pressure:NoSch…

2026/5/17 6:27:50 阅读更多 →
数据分析实战:如何用Python快速搞定线性回归模型(附代码)

数据分析实战:如何用Python快速搞定线性回归模型(附代码)

数据分析实战:如何用Python快速搞定线性回归模型(附代码) 最近几年,数据驱动的决策方式几乎渗透到了所有行业。无论是电商平台预测下个季度的销售额,还是金融公司评估贷款风险,甚至是一个健身App想根据用户…

2026/5/17 11:37:55 阅读更多 →

最新新闻

HarmonyOS ArkTS 实战:实现一个校园食堂排队取餐记录应用

HarmonyOS ArkTS 实战:实现一个校园食堂排队取餐记录应用

项目效果 本文实现一个基于 HarmonyOS 和 ArkTS 的校园食堂排队取餐记录应用。应用可以记录不同食堂窗口的排队时间、用餐时段和口味评价,并支持取餐状态切换、推荐窗口筛选、长队统计和平均等待时间统计。 最终运行效果如下:页面功能包括: 记…

2026/7/5 14:00:15 阅读更多 →
Kimi    LeetCode 3464. 正方形上的点之间的最大距离 Python3实现

Kimi LeetCode 3464. 正方形上的点之间的最大距离 Python3实现

LeetCode 3464. 正方形上的点之间的最大距离 — Python3 实现题目概述给定正方形边长 side,以及位于正方形边界上的若干点。需要从中选出 k 个点,使得任意两点之间的最小曼哈顿距离最大化。- 曼哈顿距离:|x1 - x2| |y1 - y2| - 关键约束&…

2026/7/5 14:00:15 阅读更多 →
六西格玛在AI与云原生时代的实战重构:女性技术专家的质量方法论

六西格玛在AI与云原生时代的实战重构:女性技术专家的质量方法论

1. 项目概述:一场聚焦女性科技从业者的行业活动,为何以“Sixies”为名?“Women Working in Tech Event Features Sixies”——这个标题乍看像一则简讯,但拆开来看,信息量远超表面。“Women Working in Tech”直指核心人…

2026/7/5 13:58:15 阅读更多 →
一线老师傅经验谈:选对海绵喷胶源头厂家,粘接寿命延长8年

一线老师傅经验谈:选对海绵喷胶源头厂家,粘接寿命延长8年

最容易被忽视的胶水,正在吃掉你30%的利润早些年我也走过弯路,总觉得海绵喷胶这种大通货,哪家便宜就用哪家,结果频繁出现**开胶起泡**。最严重的一个月,车间返工率飙升到**23%**,光是拆解、擦胶、重新喷涂的…

2026/7/5 13:54:14 阅读更多 →
MAA明日方舟助手:5个实用功能让你轻松实现游戏日常自动化

MAA明日方舟助手:5个实用功能让你轻松实现游戏日常自动化

MAA明日方舟助手:5个实用功能让你轻松实现游戏日常自动化 【免费下载链接】MaaAssistantArknights 《明日方舟》小助手,全日常一键长草!| A one-click tool for the daily tasks of Arknights, supporting all clients. 项目地址: https://…

2026/7/5 13:52:14 阅读更多 →
Devin工程化落地:AI协作者如何嵌入CI/CD与测试流水线

Devin工程化落地:AI协作者如何嵌入CI/CD与测试流水线

1. 项目概述:这不是一个“AI编程助手”的简单测评,而是一次对工程化落地边界的实战测绘“Software Development With Devin: Integrations, Testing, and CI/CD (Part 3)”——这个标题里藏着三个被绝大多数AI编程类内容刻意绕开的硬核关键词&#xff1a…

2026/7/5 13:44:13 阅读更多 →

日新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻