摘要: 原创出处 http://www.iocoder.cn/Spring-Boot/MapStruct/ 「芋道源码」欢迎转载,保留摘要,谢谢!

  • 1. 概述
  • 2. 快速入门
  • 3. 集成 Lombok
  • 4. @Mapping
  • 5. IDEA MapStruct 插件
  • 666. 彩蛋

本文在提供完整代码示例,可见 https://github.com/YunaiV/SpringBoot-Labs 的 lab-55 目录。

原创不易,给点个 Star 嘿,一起冲鸭!

图片

1. 概述

友情提示:MapStruct 和 Spring Boot 没有直接关系,单纯放在这个系列。

为了让应用的代码更易维护,我们往往会将项目进行分层。在《阿里巴巴 Java 开发手册》中,推荐分层如下图:

应用分层

分层之后,每一层都有自己的领域模型,即不同类型的 Bean:

  • DO(Data Object):与数据库表结构一一对应,通过DAO层向上传输数据源对象。
  • DTO(Data Transfer Object):数据传输对象,Service或Manager向外传输的对象。
  • BO(Business Object):业务对象。由Service层输出的封装业务逻辑的对象。
  • 等等...

那么,进行就需要这些对象的转换。例如说:

// 从数据库中查询用户
UserDO userDO = userMapper.selectBy(id);

// 对象转换
UserBO userBO = new UserBO();
userBO.setId(userDO.getId());
userBO.setUsername(userDO.getUsername());
// ... 还有其它属性

显然,手动进行对象的转换,虽然执行性能很高,但是开发效率非常低下,且可能会存在漏写的情况。因此,我们会选择借助框架或是工具来实现对象的转换,例如说:

友情提示:如果胖友对如下工具的性能对比感兴趣,可以阅读 Performance of Java Mapping Frameworks 文章。

  • Spring BeanUtils
  • Apache BeanUtils
  • Dozer
  • Orika
  • MapStruct
  • ModelMapper
  • JMapper

艿艿个人比较喜欢 MapStruct,原因是它基于 JSR 269 的 Java 注解处理器,自动生成对象的代码,使用便捷,性能优秀。例如说:

  • 通过创建一个 MapStruct Mapper 接口,并定义一个转换接口方法,后续交给 MapStruct 自动生成对象转换的代码即可。

如下是 MapStruct 的简介,胖友可以简单了解下:

MapStruct 是用于生成类型安全的 Bean 映射类的 Java 注解处理器。

你所要做的就是定义一个映射器接口,声明任何需要映射的方法。在编译过程中,MapStruct 将生成该接口的实现。此实现使用纯 Java 的方法调用源对象和目标对象之间进行映射,并非 Java 反射机制

与手工编写映射代码相比,MapStruct 通过生成冗长且容易出错的代码来节省时间。在配置方法的约定之后,MapStruct 使用了合理的默认值,但在配置或实现特殊行为时将不再适用。

与动态映射框架相比,MapStruct 具有以下优点:

  • 使用纯 Java 方法代替 Java 反射机制快速执行。
  • 编译时类型安全:只能映射彼此的对象和属性,不能映射一个 Order 实体到一个 Customer DTO 中等等。
  • 如果无法映射实体或属性,则在编译时清除错误报告。

2. 快速入门

示例代码对应仓库:lab-55-mapstruct-demo 。

本小节,我们来快速入门 MapStruct。新建 lab-55-mapstruct-demo 项目,作为示例项目,最终如下图所示:

项目总体结构

2.1 引入依赖

创建 pom.xml 文件,引入 MapStruct 相关依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <parent>
        <artifactId>lab-55</artifactId>
        <groupId>cn.iocoder.springboot.labs</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-55-mapstruct-demo</artifactId>

    <properties>
        <java.version>1.8</java.version>
        <mapstruct.version>1.3.1.Final</mapstruct.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${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>${java.version}</source>
                    <target>${java.version}</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${mapstruct.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

注意,一定要在 maven-compiler-plugin 插件中,声明 mapstruct-processor 为 JSR 269 的 Java 注解处理器。

2.2 UserDO

创建 UserDO 类,用户 DO。代码如下:

public class UserDO {

    /** 用户编号 **/
    private Integer id;
    /** 用户名 **/
    private String username;
    /** 密码 **/
    private String password;

    // ... 省略 setter/getter 方法
}

2.3 UserBO

创建 UserBO 类,用户 BO。代码如下:

public class UserBO {

    /** 用户编号 **/
    private Integer id;
    /** 用户名 **/
    private String username;
    /** 密码 **/
    private String password;

    // ... 省略 setter/getter 方法
}

2.4 UserConvert

创建 UserConvert 接口,作为 User 相关 Bean 的转换器。代码如下:

@Mapper // <1>
public interface UserConvert {

    UserConvert INSTANCE = Mappers.getMapper(UserConvert.class); // <2>

    UserBO convert(UserDO userDO);

}

<1> 处,添加 @Mapper 注解,声明它是一个 MapStruct Mapper 映射器。

<2> 处,通过调用 Mappers 的 #getMapper(Class<T> clazz) 方法,获得 MapStruct 帮我们自动生成的 UserConvert 实现类的对象。

<3> 处,定义 #convert(UserDO userDO) 方法,声明 UserDO 转换成 UserBO。后续,在我们每次编译该项目时,在如下目录可以看到自动生成的 UserConvert 实现类,可以用于 Debug 调试噢:

生成代码示例

2.5 UserBOTest

创建 UserBOTest 类,进行简单测试。代码如下:

public class UserBOTest {

    public static void main(String[] args) {
        // 创建 UserDO 对象
        UserDO userDO = new UserDO()
                .setId(1).setUsername("yudaoyuanma").setPassword("buzhidao");
        // <X> 进行转换
        UserBO userBO = UserConvert.INSTANCE.convert(userDO);
        System.out.println(userBO.getId());
        System.out.println(userBO.getUsername());
        System.out.println(userBO.getPassword());
    }

}

核心代码在 <X> 处,通过 UserConvert 将 UserDO 对象转换成 UserBO 对象。

运行 #main(String[] args) 方法,打印如下,符合预期:

1
yudaoyuanma
buzhidao

更多相关文章

  1. 把 WebAssembly 用于提升速度和代码重用[每日前端夜话0xBC]
  2. 无法理解如何使用javascript和jquery代码
  3. 美元。针对简单的php, post返回对象
  4. 将JavaScript对象作为Dictionary 传递给C#WCF服务
  5. Jquery Validate 正则表达式实用验证代码常用的
  6. 通过],[和创建json对象来分割字符串
  7. 我通过jQuery-ajax创建了__PHP_Incomplete_Class对象此错误
  8. 如何从Python脚本向jQuery发送JSON对象?
  9. Jquery 只执行一次的代码

随机推荐

  1. ASP.Net是什么意思?ASP.Net框架的特性有哪
  2. C语言怎么计算矩形的面积和周长
  3. Ruby如何创建数组
  4. ASP是什么
  5. c语言怎么输出字符串
  6. ASP.NET与.NET的区别是什么
  7. IO帮助类是什么?IO帮助类的实例介绍(附代码
  8. ASP.NET与ASP有什么不同
  9. 什么是XML序列化?XML序列化实例介绍(附代码
  10. asp.net是什么