当前位置: 首页 > news >正文

如何在Spring Boot项目中使用MapStruct?

在 Spring Boot 项目中使用 MapStruct 非常简单,只需几个步骤即可完成配置并发挥其强大的对象映射能力。下面是详细的集成方法和示例:

1. 添加依赖

pom.xml 中添加 MapStruct 依赖,Spring Boot 会自动处理相关配置:

<properties><mapstruct.version>1.5.5.Final</mapstruct.version>
</properties><dependencies><!-- MapStruct 核心依赖 --><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>${mapstruct.version}</version></dependency>
</dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>17</source> <!-- 根据你的JDK版本调整 --><target>17</target><annotationProcessorPaths><!-- MapStruct 注解处理器 --><path><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>${mapstruct.version}</version></path><!-- Lombok 处理器(如果使用Lombok) --><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version></path><path><groupId>org.projectlombok</groupId><artifactId>lombok-mapstruct-binding</artifactId><version>0.2.0</version></path></annotationProcessorPaths></configuration></plugin></plugins>
</build>

2. 创建映射器接口

在 Spring Boot 中,推荐使用 componentModel = "spring" 让 MapStruct 生成的映射器被 Spring 容器管理,方便依赖注入:

示例代码:
在这里插入图片描述

package com.example.demo.controller;import com.example.demo.dto.UserDTO;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/users")
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/{id}")public UserDTO getUser(@PathVariable Long id) {return userService.getUserInfo(id);}@PostMappingpublic User createUser(@RequestBody UserDTO userDTO) {return userService.saveUser(userDTO);}
}package com.example.demo.dto;import lombok.Data;
import java.time.LocalDate;@Data
public class UserDTO {private Long id;private String userName;  // 与实体类的username不同private Integer userAge;  // 与实体类的age不同private LocalDate birthDate;  // 与实体类的birthday不同private String emailAddress;  // 与实体类的email不同
}package com.example.demo.entity;import lombok.Data;
import java.time.LocalDate;@Data
public class User {private Long id;private String username;private String password;private Integer age;private LocalDate birthday;private String email;
}package com.example.demo.mapper;import com.example.demo.dto.UserDTO;
import com.example.demo.entity.User;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;// componentModel = "spring" 表示让Spring管理该映射器
@Mapper(componentModel = "spring")
public interface UserMapper {// 如果不使用Spring注入,可以通过此方式获取实例UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);// 基本映射,处理字段名不同的情况@Mapping(source = "username", target = "userName")@Mapping(source = "age", target = "userAge")@Mapping(source = "birthday", target = "birthDate")@Mapping(source = "email", target = "emailAddress", qualifiedByName = "maskEmail")UserDTO toDTO(User user);// 反向映射@Mapping(source = "userName", target = "username")@Mapping(source = "userAge", target = "age")@Mapping(source = "birthDate", target = "birthday")@Mapping(source = "emailAddress", target = "email")User toEntity(UserDTO dto);// 自定义映射方法:对邮箱进行简单脱敏@Named("maskEmail")default String maskEmail(String email) {if (email == null || !email.contains("@")) {return email;}String[] parts = email.split("@");if (parts[0].length() > 3) {return parts[0].substring(0, 3) + "***@" + parts[1];}return parts[0] + "***@" + parts[1];}
}package com.example.demo.service;import com.example.demo.dto.UserDTO;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDate;@Service
public class UserService {// 注入MapStruct生成的映射器@Autowiredprivate UserMapper userMapper;public UserDTO getUserInfo(Long id) {// 模拟从数据库获取用户实体User user = new User();user.setId(id);user.setUsername("zhang_san");user.setPassword("encrypted_password");user.setAge(28);user.setBirthday(LocalDate.of(1995, 3, 15));user.setEmail("zhangsan@example.com");// 使用映射器转换为DTOreturn userMapper.toDTO(user);}public User saveUser(UserDTO dto) {// 将DTO转换为实体User user = userMapper.toEntity(dto);// 模拟保存到数据库的逻辑user.setPassword("encrypted_" + dto.getUserName());return user;}
}

关键配置说明

  1. @Mapper(componentModel = "spring")

    • 这个配置让 MapStruct 生成的映射器实现类会被标记为 @Component,从而可以被 Spring 自动扫描并纳入容器管理
    • 之后就可以通过 @Autowired 轻松注入映射器,无需手动创建实例
  2. 与 Lombok 兼容

    • 如果项目中使用 Lombok,需要添加 lombok-mapstruct-binding 依赖解决注解处理器冲突
    • 确保 Lombok 版本与 MapStruct 版本兼容(示例中使用的组合经过验证)
  3. 生成的代码位置

    • 编译后,MapStruct 会在 target/generated-sources/annotations 目录下生成映射器的实现类
    • 可以查看这些代码了解映射逻辑,便于调试

运行效果

当访问 GET /users/1 时,会返回如下 JSON:

{"id": 1,"userName": "zhang_san","userAge": 28,"birthDate": "1995-03-15","emailAddress": "zha***@example.com"
}

(注意邮箱已通过自定义映射方法进行脱敏处理)

项目中的最佳实践

  1. 按业务模块组织映射器:每个领域模型创建独立的映射器接口
  2. 处理复杂映射:对于跨对象的复杂映射,使用 @Mappingexpression 属性或自定义方法
  3. 集合映射:直接声明集合转换方法(如 List<UserDTO> toDTOList(List<User> users)),MapStruct 会自动生成循环转换逻辑
  4. 测试映射器:编写单元测试验证映射结果,确保字段映射正确
  5. 版本兼容:保持 MapStruct 与 JDK、Spring Boot 版本的兼容性

通过这种方式,MapStruct 能够完美融入 Spring Boot 生态,大幅减少对象转换的样板代码,同时保持类型安全和高性能。

http://www.xdnf.cn/news/1456651.html

相关文章:

  • 旅游安全急救实训室助力应急处置技能实战化
  • Websocket的Key多少个字节
  • 【Big Data】云原生与AI时代的存储基石 Apache Ozone 的技术演进路径
  • 深度学习篇---SENet网络结构
  • 【C语言】第二课 基础语法
  • 【开题答辩全过程】以 基于微信小程序的宠物领养系统为例,包含答辩的问题和答案
  • 理解 C# `async` 的本质:从同步包装到状态机
  • 云手机与网络游戏相结合的优势?
  • AI大模型企业落地指南-笔记05
  • 【75】OpenCV C++实战篇——OpenCV 图像拼接、全景拼接(教程合集)
  • 【华为培训笔记】ASON原理
  • 关于嵌入式学习——嵌入式硬件3
  • 如何在MacOS上卸载并且重新安装Homebrew
  • 企业微信SCRM工具推荐:微盛AI·企微管家为什么是首选?
  • c#泛型公共类示例
  • Next.js App Router 中文件系统路由与页面跳转实践(以用户详情页面为例)
  • 1688拍立淘接口对接实战案例
  • Playwright-ui自动化工具
  • 如何设置PPTX的默认打开应用为PowerPoint
  • ​​AI生成PPT工具推荐,从此以后再也不用担心不会做PPT了​​
  • Effective Python 第10条 - 用赋值表达式减少重复代码
  • 股价暴跌后扔出 “王炸”,美团 LongCat 大模型到底是续命还是真有料?
  • Linux网络服务——基础设置
  • 【Kubernetes】知识点4
  • 吐槽一下福昕pdf阅读器高级专业版
  • git命令常用指南
  • openEuler2403安装部署Kafbat
  • 用遗传算法破解一元函数最大值问题:从原理到 MATLAB 实现
  • 关于多Agent协作框架的讨论:以产品经理工作流为例对比Sub Agent与AutoGen
  • 标注工具labelimg使用简介