返回顶部
首页 > 资讯 > 精选 >为什么使用MapStruct工具类
  • 359
分享到

为什么使用MapStruct工具类

2023-06-16 07:06:40 359人浏览 泡泡鱼
摘要

本篇内容主要讲解“为什么使用MapStruct工具类”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“为什么使用MapStruct工具类”吧!为什么需要MapStruct ?首先,我们先说一下Map

本篇内容主要讲解“为什么使用MapStruct工具类”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“为什么使用MapStruct工具类”吧!

为什么需要MapStruct ?

首先,我们先说一下MapStruct这类框架适用于什么样的场景,为什么市面上会有这么多的类似的框架。

在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。很多人都对三层架构、四层架构等并不陌生。

甚至有人说:"计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决,如果不行,那就加两层。"

但是,随着软件架构分层越来越多,那么各个层次之间的数据模型就要面临着相互转换的问题,典型的就是我们可以在代码中见到各种O,如DO、DTO、VO等。

一般情况下,同样一个数据模型,我们在不同的层次要使用不同的数据模型。如在数据存储层,我们使用DO来抽象一个业务实体;在业务逻辑层,我们使用DTO来表示数据传输对象;到了展示层,我们又把对象封装成VO来与前端进行交互。

那么,数据的从前端透传到数据持久化层(从持久层透传到前端),就需要进行对象之间的互相转化,即在不同的对象模型之间进行映射。

通常我们可以使用get/set等方式逐一进行字段映射操作,如:

personDTO.setName(personDO.getName());  personDTO.setAge(personDO.getAge());  personDTO.setSex(personDO.getSex());  personDTO.setBirthday(personDO.getBirthday());

但是,编写这样的映射代码是一项冗长且容易出错的任务。MapStruct等类似的框架的目标是通过自动化的方式尽可能多地简化这项工作。

MapStruct的使用

MapStruct是一种代码生成器,它极大地简化了基于"约定优于配置"方法的Java bean类型之间映射的实现。生成的映射代码使用纯方法调用,因此快速、类型安全且易于理解。

约定优于配置,也称作按约定编程,是一种软件设计范式,旨在减少软件开发人员需做决定的数量,获得简单的好处,而又不失灵活性。

假设我们有两个类需要进行互相转换,分别是PersonDO和PersonDTO,类定义如下:

public class PersonDO {      private Integer id;      private String name;      private int age;      private Date birthday;      private String gender;  }  public class PersonDTO {      private String userName;      private Integer age;      private Date birthday;      private Gender gender;  }

我们演示下如何使用MapStruct进行bean映射。

想要使用MapStruct,首先需要依赖他的相关的jar包,使用Maven依赖方式如下:

...  <properties>      <org.mapstruct.version>1.3.1.Final</org.mapstruct.version>  </properties>  ...  <dependencies>      <dependency>          <groupId>org.mapstruct</groupId>          <artifactId>mapstruct</artifactId>          <version>${org.mapstruct.version}</version>      </dependency>  </dependencies>  ...  <build>      <plugins>          <plugin>              <groupId>org.apache.maven.plugins</groupId>              <artifactId>maven-compiler-plugin</artifactId>              <version>3.8.1</version>              <configuration>                  <source>1.8</source> <!-- depending on your project -->                  <target>1.8</target> <!-- depending on your project -->                  <annotationProcessorPaths>                      <path>                          <groupId>org.mapstruct</groupId>                          <artifactId>mapstruct-processor</artifactId>                          <version>${org.mapstruct.version}</version>                      </path>                      <!-- other annotation processors -->                  </annotationProcessorPaths>              </configuration>          </plugin>      </plugins>  </build>

因为MapStruct需要在编译器生成转换代码,所以需要在maven-compiler-plugin插件中配置上对mapstruct-processor的引用。这部分在后文会再次介绍。

之后,我们需要定义一个做映射的接口,主要代码如下:

@Mapper  interface PersonConverter {      PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);      @Mappings(@Mapping(source = "name", target = "userName"))      PersonDTO do2dto(PersonDO person);  }

使用注解@Mapper定义一个Converter接口,在其中定义一个do2dto方法,方法的入参类型是PersonDO,出参类型是PersonDTO,这个方法就用于将PersonDO转成PersonDTO。

测试代码如下:

public static void main(String[] args) {      PersonDO personDO = new PersonDO();      personDO.setName("Hollis");      personDO.setAge(26);      personDO.setBirthday(new Date());      personDO.setId(1);      personDO.setGender(Gender.MALE.name());      PersonDTO personDTO = PersonConverter.INSTANCE.do2dto(personDO);      System.out.println(personDTO);  }

输出结果:

PersonDTO{userName='Hollis', age=26, birthday=Sat Aug 08 19:00:44 CST 2020, gender=MALE}

可以看到,我们使用MapStruct完美的将PersonDO转成了PersonDTO。

上面的代码可以看出,MapStruct的用法比较简单,主要依赖@Mapper注解。

但是我们知道,大多数情况下,我们需要互相转换的两个类之间的属性名称、类型等并不完全一致,还有些情况我们并不想直接做映射,那么该如何处理呢?

其实MapStruct在这方面也是做的很好的。

MapStruct处理字段映射

首先,可以明确的告诉大家,如果要转换的两个类中源对象属性与目标对象属性的类型和名字一致的时候,会自动映射对应属性。

那么,如果遇到特殊情况如何处理呢?

名字不一致如何映射

如上面的例子中,在PersonDO中用name表示用户名称,而在PersonDTO中使用userName表示用户名,那么如何进行参数映射呢。

这时候就要使用@Mapping注解了,只需要在方法签名上,使用该注解,并指明需要转换的源对象的名字和目标对象的名字就可以了,如将name的值映射给userName,可以使用如下方式:

@Mapping(source = "name", target = "userName")

可以自动映射的类型

除了名字不一致以外,还有一种特殊情况,那就是类型不一致,如上面的例子中,在PersonDO中用String类型表示用户性别,而在PersonDTO中使用一个Genter的枚举表示用户性别。

这时候类型不一致,就需要涉及到互相转换的问题

其实,MapStruct会对部分类型自动做映射,不需要我们做额外配置,如例子中我们将String类型自动转成了枚举类型。

一般情况下,对于以下情况可以做自动类型转换:

  •  基本类型及其他们对应的包装类型。

  •  基本类型的包装类型和String类型之间

  •  String类型和枚举类型之间

自定义常量

如果我们在转换映射过程中,想要给一些属性定义一个固定的值,这个时候可以使用 constant

@Mapping(source = "name", constant = "hollis")

类型不一致的如何映射

还是上面的例子,如果我们需要在Person这个对象中增加家庭住址这个属性,那么我们一般在PersonoDTO中会单独定义一个HomeAddress类来表示家庭住址,而在Person类中,我们一般使用String类型表示家庭住址。

这就需要在HomeAddress和String之间使用JSON进行互相转化,这种情况下,MapStruct也是可以支持的。

public class PersonDO {      private String name;      private String address;  }  public class PersonDTO {      private String userName;      private HomeAddress address;  }  @Mapper  interface PersonConverter {      PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);      @Mapping(source = "userName", target = "name")      @Mapping(target = "address",expression = "java(homeAddressToString(dto2do.getAddress()))")      PersonDO dto2do(PersonDTO dto2do);      default String homeAddressToString(HomeAddress address){          return jsON.toJSONString(address);      }  }

我们只需要在PersonConverter中在定义一个方法(因为PersonConverter是一个接口,所以在jdk 1.8以后的版本中可以定义一个default方法),这个方法的作用就是将HomeAddress转换成String类型。

default方法:Java 8 引入的新的语言特性,用关键字default来标注,被default所标注的方法,需要提供实现,而子类可以选择实现或者不实现该方法

然后在dto2do方法上,通过以下注解方式即可实现类型的转换:

@Mapping(target = "address",expression = "java(homeAddressToString(dto2do.getAddress()))")

上面这种是自定义的类型转换,还有一些类型的转换是MapStruct本身就支持的,如String和Date之间的转换:

@Mapping(target = "birthday",dateFORMat = "yyyy-MM-dd HH:mm:ss")

以上,简单介绍了一些常用的字段映射的方法,也是我自己在工作中经常遇到的几个场景

MapStruct的性能

前面说了这么多MapStruct的用法,可以看出MapStruct的使用还是比较简单的,并且字段映射上面的功能很强大,那么他的性能到底怎么样呢?

分别执行1000、10000、100000、1000000次映射的耗时分别为:0ms、1ms、3ms、6ms。

可以看到,MapStruct的耗时相比较于其他几款工具来说是非常短的。

那么,为什么MapStruct的性能可以这么好呢?

其实,MapStruct和其他几类框架最大的区别就是:与其他映射框架相比,MapStruct在编译时生成bean映射,这确保了高性能,可以提前将问题反馈出来,也使得开发人员可以彻底的错误检查。

还记得前面我们在引入MapStruct的依赖的时候,特别在maven-compiler-plugin中增加了mapstruct-processor的支持吗?

并且我们在代码中使用了很多MapStruct提供的注解,这使得在编译期,MapStruct就可以直接生成bean映射的代码,相当于代替我们写了很多setter和getter。

如我们在代码中定义了以下一个Mapper:

@Mapper  interface PersonConverter {      PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);      @Mapping(source = "userName", target = "name")      @Mapping(target = "address",expression = "java(homeAddressToString(dto2do.getAddress()))")      @Mapping(target = "birthday",dateFormat = "yyyy-MM-dd HH:mm:ss")      PersonDO dto2do(PersonDTO dto2do);      default String homeAddressToString(HomeAddress address){          return JSON.toJSONString(address);      }  }

经过代码编译后,会自动生成一个PersonConverterImpl:

@Generated(      value = "org.mapstruct.ap.MappingProcessor",      date = "2020-08-09T12:58:41+0800",      comments = "version: 1.3.1.Final, compiler: javac, environment: Java 1.8.0_181 (oracle Corporation)"  )  class PersonConverterImpl implements PersonConverter {      @Override      public PersonDO dto2do(PersonDTO dto2do) {          if ( dto2do == null ) {              return null;          }          PersonDO personDO = new PersonDO();          personDO.setName( dto2do.getUserName() );          if ( dto2do.getAge() != null ) {              personDO.setAge( dto2do.getAge() );          }          if ( dto2do.getGender() != null ) {              personDO.setGender( dto2do.getGender().name() );         }          personDO.setAddress( homeAddressToString(dto2do.getAddress()) );          return personDO;      }  }

在运行期,对于bean进行映射的时候,就会直接调用PersonConverterImpl的dto2do方法,这样就没有什么特殊的事情要做了,只是在内存中进行set和get就可以了。

所以,因为在编译期做了很多事情,所以MapStruct在运行期的性能会很好,并且还有一个好处,那就是可以把问题的暴露提前到编译期。

使得如果代码中字段映射有问题,那么应用就会无法编译,强制开发者要解决这个问题才行。

到此,相信大家对“为什么使用MapStruct工具类”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: 为什么使用MapStruct工具类

本文链接: https://lsjlt.com/news/282791.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 为什么使用MapStruct工具类
    本篇内容主要讲解“为什么使用MapStruct工具类”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“为什么使用MapStruct工具类”吧!为什么需要MapStruct ?首先,我们先说一下Map...
    99+
    2023-06-16
  • SpringBoot + MapStruct 属性映射工具的使用详解
    1. MapStruct 是什么? 截取下官方的原话 我给翻译了一下 说白了 当你的对象A有几十个属性 而另一个对象B 与A比较只有一些细微的差别 那么这时候只需要映射过去即可 而...
    99+
    2024-04-02
  • Java实体映射工具MapStruct使用方法详解
    目录1.序 2.简单用例 3.使用详解 1)关于接口注解@Mapper几种属性用法详解 2) 其他方法级别注解 总结1.序 通常在后端开发中经常不直接返回实体Entity类,经过处...
    99+
    2024-04-02
  • AbstractProcessor扩展MapStruct自动生成实体映射工具类
    目录1 背景2 现有技术3 扩展设计3.1 mapstruct 介绍3.2 改进方案4 实现4.1 技术依赖4.2 实现步骤5 实践5.1 引入依赖5.2 对象定义5.3 生成结果5...
    99+
    2023-01-28
    AbstractProcessor MapStruct MapStruct实体映射工具类
  • Mapstruct的具体介绍与使用
    我是 ABin-阿斌:写一生代码,创一世佳话,筑一览芳华。 如果小伙伴们觉得我的文章不错,记得一键三连哦 文章目录 一、mapstruct简介二、mapstruct与其他映射对比三、m...
    99+
    2023-09-03
    java
  • 工具类之关于RestTemplateUtil工具类的使用
    目录工具类-RestTemplateUtil工具类代码可直接复制使用RestTemplate配置类和工具类工具类-RestTemplateUtil工具类 代码可直接复制使用 配置Re...
    99+
    2022-11-13
    工具类使用  RestTemplateUtil工具类 RestTemplateUtil的使用
  • hutool工具类怎么使用
    这篇文章主要介绍“hutool工具类怎么使用”,在日常操作中,相信很多人在hutool工具类怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”hutool工具类怎么使用”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-21
  • AbstractProcessor扩展MapStruct如何自动生成实体映射工具类
    今天小编给大家分享一下AbstractProcessor扩展MapStruct如何自动生成实体映射工具类的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,...
    99+
    2023-07-05
  • Java工具类RelativeDateFormat怎么使用
    要使用Java工具类RelativeDateFormat,您可以按照以下步骤进行操作:1. 下载RelativeDateFormat...
    99+
    2023-10-20
    Java
  • 性能爆棚的实体转换复制工具MapStruct如何使用
    这篇“性能爆棚的实体转换复制工具MapStruct如何使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“性能爆棚的实体转换复...
    99+
    2023-07-05
  • Java好用的工具类是什么
    Java中有很多好用的工具类,以下是一些常用的工具类:1. StringUtils:Apache Commons Lang中的工具类...
    99+
    2023-09-25
    java
  • 怎么使用Java工具类库hutool
    本篇内容介绍了“怎么使用Java工具类库hutool”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!简介Hutool是Hu + tool的自造...
    99+
    2023-06-16
  • Android中MediaPlayer工具类怎么使用
    在Android中,MediaPlayer是一个用于播放音频和视频的工具类。下面是一些使用MediaPlayer的基本步骤: 创...
    99+
    2023-10-21
    Android MediaPlayer
  • Hutool工具类使用详解
    当今,Java开发者需要处理各种各样的任务,这包括但不限于:日期操作、加密算法、文件操作、Excel数据处理、网络请求等等。而在处理这些任务时,为了提高效率、降低开发难度和复杂度,我们需要借助一些工具类库。Hutool是一个Java工具类库...
    99+
    2023-08-25
    java 开发语言
  • Java工具类之什么是包装类
    这篇文章主要介绍“Java工具类之什么是包装类”,在日常操作中,相信很多人在Java工具类之什么是包装类问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java工具类之什么是包装类”的疑惑有所帮助!接下来,请跟...
    99+
    2023-06-16
  • Hutool Java工具类库_ExcelUtil怎么使用
    这篇文章主要介绍“Hutool Java工具类库_ExcelUtil怎么使用”,在日常操作中,相信很多人在Hutool Java工具类库_ExcelUtil怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作...
    99+
    2023-06-21
  • TypeScript内置工具类型怎么使用
    这篇文章主要介绍“TypeScript内置工具类型怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“TypeScript内置工具类型怎么使用”文章能帮助大家解决问题。一、什么是ts内置工具类型T...
    99+
    2023-07-05
  • vue开发使用什么工具
    本教程操作环境:windows7系统、vue3版,DELL G3电脑。vue开发工具1、BootstrapVue用于为 Vuejs 构建 Bootstrap 接口的开源库。链接https://bootstrap-vue.org/2、VueX...
    99+
    2023-05-14
    vue3
  • Springboot工具类ReflectionUtils使用教程
    目录前言ReflectionUtils对属性的操作对方法的操作前言 ReflectionUtils应该是Springboot内置工具类梳理的最后一篇了,可能很多人都没有听说过这个工具...
    99+
    2022-12-30
    Springboot工具类ReflectionUtils Springboot ReflectionUtils
  • Springboot工具类StringUtils使用教程
    目录org.springframework.util.StringUtils字符串操作在实际的业务开发中,除了经常有针对对象的判断或操作以外,经常也会遇到的就是字符串的判断和操作。比...
    99+
    2022-12-30
    Springboot工具类StringUtils Springboot StringUtils
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作