【springboot进阶】优雅使用 MapStruct 进行类复制
创始人
2024-04-08 04:03:10
0

项目中经常会遇到这样的一个情况:从数据库读取到数据,并不是直接返回给前端做展示的,还需要字段的加工,例如记录的时间戳是不需要的、一些敏感数据更是不能等等。传统的做法就是创建一个新的类,然后写一堆的get/set方法进行赋值,如果字段很多的话,那简直是噩梦,有时候还担心会漏掉等等。

 一、MapStruct 介绍

MapStruct 简单来说就是一个属性映射工具,主要用于解决数据模型之间不通用的情况。这里主要说一下它的优点在于性能好,像笔者在未接触 MapStruct 以前一直使用的 BeanUtils 工具进行转换,当时也知道这样性能不好,但是为了能偷懒,所以...

其实 MapStruct 也不是有神秘之处,其实原理在于,Java程序执行的过程,是由编译器先把java文件编译成class字节码文件,然后由JVM去解释执行class文件。Mapstruct正是在java文件到class这一步帮我们实现了转换方法,即做了预处理,提前编译好文件。

二、MapStruct 配置

需要引入 mapstruct 和 mapstruct-processor,同时 scope 设置为 provided ,即它只影响到编译,测试阶段。

org.mapstructmapstruct1.5.0.Finalprovided
org.mapstructmapstruct-processor1.5.0.Finalprovided

三、MapStruct 使用

这边演示的是一般项目中,从数据库读取到数据,到返回前端展示的过程。

 假设我们有一个student表,实体字段信息如下。

/*** 

* 学生表*

** @author Liurb* @since 2022-11-13*/ @Getter @Setter @TableName("demo_student") public class Student implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.AUTO)private Integer id;/*** 学生名称*/@TableField("`name`")private String name;/*** 学生年龄*/@TableField("age")private Integer age;/*** 学生性别*/@TableField("sex")private String sex;/*** 创建时间*/@TableField("created_at")private LocalDateTime createdAt;}

但是前端页面展示的时候,某些字段需要调整。例如,学生信息需要展示在首页和列表页,他们的数据模型字段名称是不一致的。

学生首页展示vo 需要调整学生的 id 为 userId, 学生名称为 userName 。

/*** 学生首页展示vo*** @Author LiuRuiBin* @Date 2022/11/13*/
@Data
public class StudentHomeVo {private Integer userId;private String userName;private Integer age;private String sex;}

学生分页展示vo 需要调整学生的性别为 gender 。 

/*** 学生分页展示vo*** @Author LiuRuiBin* @Date 2022/11/13*/
@Data
public class StudentPageVo {private Integer id;private String name;private Integer age;private String gender;}

创建 学生实体的mapper,由于要区分 mybatis-plus 的底层mapper,所以这里的命名以 StructMapper 结尾,尽量避免重名的情况。所以注意 @Mapper 注解也要使用 org.mapstruct 包下的。

/*** 学生实体转换接口** 定义这是一个MapStruct对象属性转换接口,在这个类里面规定转换规则** @Author LiuRuiBin* @Date 2022/11/13*/
@Mapper
public interface StudentStructMapper {/*** 获取该类自动生成的实现类的实例**/StudentStructMapper INSTANCES = Mappers.getMapper(StudentStructMapper.class);/*** 这个方法就是用于实现对象属性复制的方法** @Mapping 注解 用于定义属性复制规则* source 指定源对象属性* target指定目标对象属性** @param student 这个参数就是源对象,也就是需要被复制的对象* @return 返回的是目标对象,就是最终的结果对象*/@Mappings({@Mapping(source = "id", target = "userId"),@Mapping(source = "name", target = "userName")})StudentHomeVo toStudentHomeVo(Student student);/*** 也可以实现多个复制方法,一般将一个实体源对象的转换写在一起** @param student* @return*/@Mapping(source = "sex", target = "gender")StudentPageVo toStudentPageVo(Student student);
}

四、测试

我们创建一个controller,模拟一般项目的接口请求。

/*** mapstruct实例控制器** @Author LiuRuiBin* @Date 2022/11/13*/
@RestController
@RequestMapping("/demo_api/mapstruct")
public class MapStructController {@ResourceStudentService studentService;@GetMapping("/home/{id}")public StudentHomeVo home(@PathVariable("id")Integer id) {Student student = studentService.getById(id);StudentHomeVo studentHomeVo = StudentStructMapper.INSTANCES.toStudentHomeVo(student);return studentHomeVo;}@GetMapping("/page")public List page() {List students = studentService.list();List studentPageVos = students.stream().map(item -> {StudentPageVo studentPageVo = StudentStructMapper.INSTANCES.toStudentPageVo(item);return studentPageVo;}).collect(Collectors.toList());return studentPageVos;}}

数据表的记录如下

调用首页展示接口的情况如下,可以看到,返回的新字段已经成功赋值。

 接下来,看一下分页的数据,新字段 性别 gender 也同样赋值成功。

 五、遇到的坑

1、java.lang.NoSuchMethodError

如果现在我们将学生首页vo类的 age 字段,调整为 userAge,运行项目,在请求一次接口,你会发现这时候会报错,提示找不到 setAge 方法。

为什么会这样呢?其实原因在于上面说的 MapStruct 工作原理,这时候查看转换接口的实现就可以知道是什么情况了。

 实现类还是调用的 setAge 方法进行赋值,但是我们的 StudentHomeVo 已经被我们改过,没有这个方法了,所以运行时候就会报错了。

那么这种情况如何解决了,其实也很简单,重新编译一次项目就可以了。

 重新编译运行,再请求一次接口,可以看到成功返回,并且新字段也有赋值。 

如果发现调整了字段,或者改过转换mapper的东西后,出现奇奇怪怪的情况,一种重新编译一下项目就能解决。

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...