如何在Spring应用中用MapStruct简化多层DTO嵌套映射?
核心简化思路
利用MapStruct的自动同名映射和嵌套映射方法自动识别特性,无需逐个编写@Mapping注解,就能快速完成复杂DTO到实体的转换。
步骤1:添加MapStruct依赖
Maven(pom.xml)
<dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.5.5.Final</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.5.5.Final</version> <scope>provided</scope> </dependency>
Gradle(build.gradle)
implementation 'org.mapstruct:mapstruct:1.5.5.Final' annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final'
步骤2:编写MapStruct映射器
定义一个Mapper接口,利用自动映射和嵌套映射方法,完全避免逐个写@Mapping:
import org.mapstruct.Mapper; import org.mapstruct.Mapping; @Mapper(componentModel = "spring") // 生成Spring可直接注入的Bean public interface MenuMapper { // 主映射方法:将MenuSaveQuery转为Menu // 同名属性(path/name/component/redirect)自动映射,meta字段通过子方法处理 @Mapping(target = "meta", source = ".") // 用当前query对象作为源映射到meta字段 Menu toMenu(MenuSaveQuery query); // 子映射方法:MapStruct会自动实现该方法,将query中对应字段映射到MenuMeta // 所有同名字段(title/icon/hideMenu等)自动匹配,无需额外注解 MenuMeta toMenuMeta(MenuSaveQuery query); }
步骤3:在Spring中使用映射器
直接注入MenuMapper,调用方法完成转换:
import org.springframework.stereotype.Service; @Service public class MenuService { private final MenuMapper menuMapper; // Spring 4.3+支持构造注入无需@Autowired public MenuService(MenuMapper menuMapper) { this.menuMapper = menuMapper; } public Menu save(MenuSaveQuery query) { return menuMapper.toMenu(query); } }
原理说明
- 自动同名映射:MapStruct会自动匹配源对象和目标对象中名称、类型完全一致的字段(如
Menu.path和MenuSaveQuery.path),无需手动指定@Mapping。 - 嵌套映射自动识别:当需要映射Menu的
meta字段(类型MenuMeta)时,MapStruct会查找是否存在MenuMeta toMenuMeta(MenuSaveQuery)这样的方法,找到后自动调用该方法生成MenuMeta实例并赋值给Menu的meta属性。 - 多余字段自动忽略:
MenuSaveQuery中的parentId字段在Menu中不存在,MapStruct会自动忽略该字段的映射,无需额外配置。
特殊情况处理(可选)
如果存在字段名不一致的情况,只需针对个别字段添加@Mapping即可,比如假设MenuMeta的title字段对应query的menuTitle:
@Mapping(target = "title", source = "menuTitle") MenuMeta toMenuMeta(MenuSaveQuery query);
内容的提问来源于stack exchange,提问作者Lyle
相关产品推荐
相关产品推荐

