MapStruct到底是什么?

一、简介

现在的分布式系统中模块划分越来越细,不同模块的实体、DTO、DO等需要进行转换,这么多工程处理起来不是那么简单。

MapStruct 就是这样的一个属性映射插件,用于为Java Bean生成类型安全且高性能的映射。它基于编译阶段生成get/set代码,此实现过程中没有反射,不会造成额外的性能损失。只需要定义一个 Mapper 接口,MapStruct 就会自动实现这个映射接口,避免了繁琐的映射实现。

🍭 官网 - 🍤 官方示例

优点

与手工编写映射代码相比

  • MapStruct通过生成冗长且容易出错的代码来节省时间。

与动态映射框架相比

  • 简单泛型智能转换;
  • 效率高:无需手动 set/get 或 implements Serializable 以达到深拷贝;
  • 性能更高:使用简单的 Java 方法调用代替反射;
  • 编译时类型安全:只能映射相同名称或带映射标记的属性;
  • 编译时产生错误报告:如果映射不完整(存在未被映射的目标属性)或映射不正确(找不到合适的映射方法或类型转换)则会在编译时抛出异常。

二、Demo

2.1 导入依赖

使用该插件主要需要导入两个包:

::: details Maven | Gradle

Maven

<dependency>
        <groupId>org.mapstruct</groupId>
        <!-- jdk8以下就使用mapstruct -->
        <artifactId>mapstruct-jdk8</artifactId>
        <version>1.3.0.Final</version>
    </dependency>
				<!-- 注解处理器 -->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-processor</artifactId>
        <version>1.3.0.Final</version>
    </dependency>

Gradle

plugins {
    ...
    id "com.diffplug.eclipse.apt" version "3.26.0" // Only for Eclipse
}

dependencies {
    ...
    compile 'org.mapstruct:mapstruct:1.4.2.Final'

    annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'
    testAnnotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final' // if you are using mapstruct in test code
}
...

2.2 示例代码

::: details domain、vo、mapper、controller

domain/Person.java

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Person {

    private Long id;

    private String name;

    private Integer age;

    private Integer sex;

}

vo/PersonVO.java

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PersonVO {
    private Long personId;
    private String personName;
    private Integer age;
}

mapper/PersonMapper.java

@Mapper(componentModel = "spring")
public interface PersonMapper {
    /**
     * ClassLoader 的方式获取当前 mapper (可以不用)
     */
    PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
    /**
     * 实体转VO
     * source
     * @param person
     * @return PersonVO
     */
    @Mappings({
            @Mapping(source = "id", target = "personId"),
            @Mapping(source = "name", target = "personName")
    })
    PersonVO toPersonVO(Person person);

    /**
     * VO转实体
     *
     * @param person
     * @return PersonVO
     */
    @Mappings({
            @Mapping(source = "personId", target = "id"),
            @Mapping(source = "personName", target = "name"),
      			@Mapping(target = "sex", ignore = true),
    })
    Person toPerson(PersonVO person);

}

Controller

@RestController
@RequestMapping("/api")
public class TestMapStructController {

    @Autowired
    PersonMapper personMapper;

    @GetMapping("convert")
    public List<Object> convertEntity() {
        ArrayList<Object> objectList = new ArrayList<>();
        Person person = Person.builder()
                .id(5L)
                .name("zhangsan")
                .age(12)
                .sex(1)
                .build();
        objectList.add(person);

        PersonVO personVO = personMapper.toPersonVO(person);
        Person person1 = personMapper.toPerson(personVO);
        objectList.add("person 转 personVO" + personVO);
        objectList.add("personVO 转 person" + person1);
        return objectList;
    }
}

打包后会看见 mapstruct 为我们生成了 mapper 的实现类

三、 注解介绍

@Mapper :MapStruct 注解处理器会扫描这个注解

先介绍一下 @Mapper 注解的 componentModel 属性,该属性用于自动生成的接口实现类的组件类型,这个属性支持四个值:

1.default : 这是默认的情况,mapstruct 不使用任何组件类型, 可以通过Mappers.getMapper(Class)方式获取自动生成的实例对象。

2.cdi : 生成的映射器是一个应用程序范围的 CDI bean,可以通过 @Inject 检索

3.spring : 生成的实现类上面会自动添加一个@Component注解,可以通过Spring的 @Autowired方式进行注入

4.jsr330 : 生成的实现类上会添加@javax.inject.Named 和@Singleton注解,可以通过 @Inject注解获取

@Mappings:配置多个@Mapping

@Mapping 属性映射,若源对象属性与目标对象名字一致,会自动映射对应属性

1.source :参数类的属性

2.target :要转换的类的属性

3.ignore :配合 target 使用,表示改转换类的的属性不需要映射

4.expression :配合 target 使用,表示改转换类的的属性使用指定的表达式进行转换

@Mapping(
         target = "someProp",
         expression = "java(new TimeAndFormat( s.getTime(), s.getFormat() ))"
)

5.expression :配合 target 使用,表示改转换类的的属性使用指定的表达式进行转换

@Mapping(
         target = "someProp",
         expression = "java(new TimeAndFormat( s.getTime(), s.getFormat() ))"
)

其他请参考源文件或官网,后续用到再补充

到此这篇关于MapStruct到底是什么?的文章就介绍到这了,更多相关MapStruct的使用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • MapStruct实体转换及List转换的方法讲解

    开发中,我们经常需要将PO转DTO.DTO转PO等一些实体间的转换.比较出名的有BeanUtil 和ModelMapper等,它们使用简单,但是在稍显复杂的业务场景下力不从心.MapStruct这个插件可以用来处理domin实体类与model类的属性映射,可配置性强.只需要定义一个 Mapper 接口,MapStruct 就会自动实现这个映射接口,避免了复杂繁琐的映射实现.MapStruct官网地址: http://mapstruct.org/ 引入依赖 <dependency> <gr

  • MapStruct实体间转换的简单用法

    摘要: 在实际项目中,我们经常需要将PO转DTO.DTO转PO等一些实体间的转换.比较出名的有BeanUtil 和ModelMapper等,它们使用简单,但是在稍显复杂的业务场景下力不从心.MapStruct这个插件可以用来处理domin实体类与model类的属性映射,可配置性强. 建立Maven项目 MapStruct需要醒目构建工具(如Maven)支持,如果项目结构不标准,可能无法生成对应的转换类.这里我使用Maven构建工程. <properties> <org.mapstruct

  • MapStruct处理Java中实体与模型间不匹配属性转换的方法

    摘要: 前面介绍了MapStrut简单用法,MapStrut的最重要的特点就是处理Java中实体与模型间不匹配属性的转换. 实体模型 有一个User对象: public class User { private Integer id; private String name; private double account; private boolean married; // setters, getters, toString() } 有一个Employee 对象: public class

  • Java MapStruct解了对象映射的毒

    前言 MVC模式是目前主流项目的标准开发模式,这种模式下框架的分层结构清晰,主要分为Controller,Service,Dao.分层的结构下,各层之间的数据传输要求就会存在差异,我们不能用一个对象来贯穿3层,这样不符合开发规范且不够灵活. 我们常常会遇到层级之间字段格式需求不一致的情况,例如数据库中某个字段是datetime日期格式,这个时间戳在数据库中的存储值为2020-11-06 23:59:59.999999,但是传递给前端的时候要求接口返回yyyy-MM-dd的格式,或者有些数据在数据

  • Java编码辅助工具Mapstruct用法详解

    前言 项目开发中,业务分层会涉及不同类型的Bean之间需要相互转换,如PO与DTO之间,PO与VO之间等.手动编码setter/getter各个对应属性,会显得臃肿繁琐.通过Mapstruct框架可简单方便地完成这一工作. 如何引入: IntelliJ IDEA中安装MapStruct Support插件:File -> Settings -> Plugins 搜索 MapStruct support 安装,同时File -> Settings -> Compiler ->

  • MapStruct到底是什么?

    一.简介 现在的分布式系统中模块划分越来越细,不同模块的实体.DTO.DO等需要进行转换,这么多工程处理起来不是那么简单. MapStruct 就是这样的一个属性映射插件,用于为Java Bean生成类型安全且高性能的映射.它基于编译阶段生成get/set代码,此实现过程中没有反射,不会造成额外的性能损失.只需要定义一个 Mapper 接口,MapStruct 就会自动实现这个映射接口,避免了繁琐的映射实现.

  • 代码中到底应不应当写注释?

    当很多前辈教育后辈应当多写注释的时候,当网络上充满了有关程序员从不写注释的段子的时候,这是一个非常有争议的话题.作为一个标题党,容我先修正一下我的观点:我认为如果代码写得足够好,那么大多数注释是多余的,我们应该通过写出更好的代码来代替更多注释. 注释的确有其用途,但大部分情况下,程序员在滥用注释.我是反对夹杂在代码间的注释的,我认为注释应当从代码中独立出来--通常被称为文档. 请看下面一段代码. 复制代码 代码如下: /* /static/market/checkout.js 2014.7.2

  • Go语言到底有没有引用传参(对比 C++ )

    C++ 中三种参数传递方式 值传递: 最常见的一种传参方式,函数的形参是实参的拷贝,函数中改变形参不会影响到函数外部的形参.一般是函数内部修改参数而又不希望影响到调用者的时候会采用值传递. 指针传递 形参是指向实参地址的一个指针,顾名思义,在函数中对形参指向的内容操作,实参本身会被修改. 引用传递 在 C++ 中,引用是变量的别名,实际上是同一个东西,在内存中也存在同一个地址.换句话说,不管在哪里对引用操作,都相当直接操作被引用的变量. 下面看 demo: #include <iostream>

  • Javascript中的Prototype到底是什么

    Javascript也是面向对象的语言,但它是一种基于原型Prototype的语言,而不是基于类的语言.在Javascript中,类和对象看起来没有太多的区别. 什么是prototype: function定义的对象有一个prototype属性,prototype属性又指向了一个prototype对象,注意prototype属性与prototype对象是两个不同的东西,要注意区别.在prototype对象中又有一个constructor属性,这个constructor属性同样指向一个constr

  • 基于AngularJS实现页面滚动到底自动加载数据的功能

    要实现这个功能,可以通过 https://github.com/sroze/ngInfiniteScroll 这个第三方控件来实现.步骤如下: 1. 下载ng-infinite-scroll.js程序 http://sroze.github.io/ngInfiniteScroll/ 目前版本是1.0.0 2. 如果你是用的jQuery2.0以上版本,还需要修改ng-infinite-scroll.js程序,将所有的将所有的$window.xxx改为$(window).xxx, elem.xxx改

  • Bootstrap中data-target 到底是什么

    data-target 与data-toggle 还有data-spy 文档总是给人一种很突兀的方式给出来,然后又没有好好解释或者是我看的不够仔细? HTML5允许开发者自由为其标签添加属性,这种自定义属性一般用"data-"开头. 我目前理解到在bootstrap中data-target,data-toggle等属性主要有两种作用: [1.]在CSS中作标签选择器用. 如: [data-toggle="buttons"] > .btn input[type=

  • 微信小程序去哪里找 小程序到底如何使用(附小程序名单)

    微信小程序要去哪里找?又该怎么用?秘密全在这里 微信小程序正式发布 看完你也会玩小程序!  2017年1月9日,是一个值得载入互联网史册的日子. 这一天,零点刚过,张小龙和他的团队,在夜色笼罩下,正式发布了微信小程序. 所以,从这一刻开始,只要有开发者登录小程序后台,并在「开发管理」页面点击了「发布」按钮,就会有一个小程序,降临到这个世界上. 而微信小程序,这个设定为「无处不在」的产品,切切实实地「在」你身边了,并即将给你的生活带来新的变化. 那么,小程序到底是什么?小程序的入口在哪里?小程序到

  • 老生常谈js中0到底是 true 还是 false

    想到一个好玩的,运行如下 javascript : if ('0') alert("'0' is true"); if ('0' == false) alert("'0' is false"); 结果是,两次都 alert 了!那么 '0' 到底是 true 还是 false 呢? 答案是:在js做比较的时候,有这样的三条规则: • 如果比较的两者中有bool,会把 bool 先转换为对应的 number,即 0 和 1 • 如果比较的双方中有一方为number一方

  • ionic js 复选框 与普通的 HTML 复选框到底有没区别

     ionic 复选框 ionic 复选框(checkbox)与普通的 HTML 复选框没什么区别,以下实例演示了 ionic 复选框 ion-checkbox 的应用. <ion-checkbox ng-model="isChecked">复选框标签</ion-checkbox> 实例 实例中,会根据复选框是否选中,修改 checked 值,true 为选中, false 为未选中. HTML 代码 <ion-header-bar class="

  • mysql VARCHAR的最大长度到底是多少

    以前一直都认为有两个字节来记录长度(长度小也可以用一个字节记录),所以这个问题当时觉得就挺无聊的不过后来群里有人给了解释,突然才发现原来事情不是这么简单 MYSQL COMPACT格式,每条记录有一个字节来表示NULL字段分布,如果表中有字段允许为空,则最大只能定到65532,如果没有字段允许为空,则那个字节可以节省,最大可以定义到65533,不知道是不是这个原因 于是上网看了些资料,又在本地做了些实验,原来vachar的最大长度真的是不定的(根据是否有非空字段来决定) 在本地做了下实验,inn

随机推荐