Java中MapStruct入门使用及对比

 更新时间:2023年12月06日 09:57:24   作者:檀越剑指大厂  
MapStruct是一个Java注解处理器框架,用于简化Java Bean之间的映射,本文主要介绍了Java中MapStruct入门使用及对比,感兴趣的可以了解一下

一.简单介绍

1.什么是 MapStruct?

MapStruct 是一个 Java 注解处理器框架,用于简化 Java Bean 之间的映射。它通过生成映射代码来消除手动编写映射代码的繁琐工作,从而提高开发效率。

2.MapStruct 的特点

  • 简化映射: MapStruct 旨在简化 Java Bean 之间的映射,减少手动编写映射代码的工作量。
  • 注解处理器: MapStruct 使用注解处理器技术,在编译时生成映射代码,而不是在运行时进行反射。
  • 类型安全: 通过在映射接口上使用注解,MapStruct 能够在编译时检查映射的正确性,提供类型安全性。
  • 支持自定义映射逻辑: 尽管 MapStruct 提供了默认的映射规则,但你仍然可以通过在映射接口中定义自定义方法来指定特定的映射逻辑。

二.基础使用

1.添加依赖

添加依赖: 首先,在你的项目中添加 MapStruct 的依赖。你可以在 Maven 或 Gradle 中进行配置。

Maven:

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.4.2.Final</version> <!-- 使用最新版本 -->
</dependency>

Gradle:

implementation 'org.mapstruct:mapstruct:1.4.2.Final' // 使用最新版本
annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'

2.定义映射接口

定义映射接口: 创建一个带有@Mapper注解的接口,定义映射方法。

@Mapper
public interface CarMapper {
    CarDto carToCarDto(Car car);
}

3.编写配置

编写映射配置: 如果需要自定义映射逻辑,可以在映射接口中定义自定义方法,或者使用@Mapping注解。

@Mapper
public interface CarMapper {
    @Mapping(source = "make", target = "manufacturer")
    CarDto carToCarDto(Car car);
}

4.生成代码

生成映射代码: 编译项目时,MapStruct 注解处理器将生成映射代码。

5.调用方法

调用映射方法: 在应用程序中调用生成的映射方法。

CarMapper carMapper = Mappers.getMapper(CarMapper.class);
CarDto carDto = carMapper.carToCarDto(car);

以上是 MapStruct 的基本介绍和使用步骤。通过这些步骤,你可以轻松地实现 Java Bean 之间的映射,同时保持代码的简洁和易维护性。

三.封装使用

1.FromConverter

public interface FromConverter<T, FROM> {

    T from(FROM from);

    List<T> from(List<FROM> list);

    default PageBean<T> from(PageBean<FROM> page) {
        PageBean<T> result = new PageBean<>();
        result.setTotalElements(page.getTotalElements());
        result.setNumber(page.getNumber());
        result.setSize(page.getSize());
        result.setTotalPages(page.getTotalPages());
        result.setNumberOfElements(page.getNumberOfElements());
        result.setContent(this.from(page.getContent()));
        return result;
    }

    default PageBean<T> from(IPage<FROM> page) {
        PageBean<T> result = new PageBean<>();
        result.setTotalElements((int) page.getTotal());
        result.setNumber((int) page.getCurrent());
        result.setSize((int) page.getSize());
        result.setTotalPages((int) page.getPages());
        result.setNumberOfElements(page.getRecords().size());
        result.setContent(this.from(page.getRecords()));
        return result;
    }
}

2.PropertyCopier

public interface PropertyCopier<TARGET, T> {
    void copy(@MappingTarget TARGET target, T t);
}

3.ToConverter

public interface ToConverter<T, TO> {
    TO to(T t);

    List<TO> to(List<T> list);

    default PageBean<TO> to(PageBean<T> page) {
        PageBean<TO> result = new PageBean<>();
        result.setTotalElements(page.getTotalElements());
        result.setNumber(page.getNumber());
        result.setSize(page.getSize());
        result.setTotalPages(page.getTotalPages());
        result.setNumberOfElements(page.getNumberOfElements());
        result.setContent(this.to(page.getContent()));
        return result;
    }

    default PageBean<TO> to(IPage<T> page) {
        PageBean<TO> result = new PageBean<>();
        result.setTotalElements((int) page.getTotal());
        result.setNumber((int) page.getCurrent());
        result.setSize((int) page.getSize());
        result.setTotalPages((int) page.getPages());
        result.setNumberOfElements(page.getRecords().size());
        result.setContent(this.to(page.getRecords()));
        return result;
    }
}

4.TwoWayConverter

public interface TwoWayConverter<SRC, DEST> extends ToConverter<SRC, DEST>, FromConverter<SRC, DEST> {
}

5.基本使用

@Data
public class ChatbotDTO {

    private Integer id;
    private String question;
    private String response;
    private Date createTime;
    private Integer isDelete;

    @Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
    public interface Converter extends FromConverter<ChatbotDTO, Chatbot> {
        Converter INSTANCE = Mappers.getMapper(Converter.class);
    }
}
@Data
public class Chatbot extends Model<Chatbot> {
    private Integer id;
    private String question;
    private String response;
    private Date createTime;
    private Integer isDelete;
}

6.原理分析

打开 target 目录,可以看到如图所示的编译后生成的类,说明在编译器就生成了对应的 DTO,相比其他 2 种方式在运行时生成 DTO 更加高效。

7.使用技巧

  • 忽略字段映射
  • 源对象与目标对象属性名不符的映射方法
  • 直接设置特定值
  • 表达式映射
  • 自定义映射

四.工具对比

1.概述

MapStruct、Apache BeanUtils 以及 Spring BeanUtils 都是用于 Java Bean 之间属性复制的工具,但它们有一些区别,包括实现方式、性能、功能等方面。

2.MapStruct

优势:

  • 编译时检查: MapStruct 在编译时生成映射代码,提供了类型安全性,可以在编译时捕获一些映射错误。
  • 性能: 由于生成的映射代码是直接的 Java 代码,MapStruct 通常在性能上优于运行时反射的解决方案。
  • 可配置性: 提供了很高的自定义能力,你可以在映射接口中定义自定义方法或使用@Mapping注解来指定映射规则。
  • MapStruct 能自动的将名字一样,类型不一致的属性值进行转化再赋值(仅限基本类型的包装类型,如果转化值适配不了对应类型会报错

不足:

  • 学习曲线: 对于初学者而言,可能需要一些时间来理解和配置 MapStruct。

3.Apache BeanUtils

优势:

  • 简单易用: Apache BeanUtils 提供了简单的 API,易于上手。
  • 反射: 使用反射机制实现属性复制,可以在运行时处理动态对象。

不足:

  • 性能: 相对于 MapStruct,Apache BeanUtils 在性能上可能较慢,因为它使用反射进行属性复制。
  • 类型安全: 由于是在运行时进行反射,缺乏编译时类型检查。

4.Spring BeanUtils

优势:

  • 集成 Spring: Spring BeanUtils 是 Spring 框架的一部分,可以很容易地集成到 Spring 应用程序中。
  • 简化代码: 提供了一些方便的方法,可以简化属性复制的代码。

不足:

  • 性能: 与 Apache BeanUtils 类似,Spring BeanUtils 也是使用反射,因此性能相对较低。
  • 可配置性: 相较于 MapStruct,可配置性相对较低。

5.总结:

  • MapStruct 提供了编译时类型检查和高度可配置性,适用于需要更高性能和更复杂映射规则的场景。

  • Apache BeanUtils 和 Spring BeanUtils 简单易用,适用于简单的属性复制场景,但在性能和类型安全性方面可能相对较差。

选择使用哪个工具取决于你的具体需求,如果性能和类型安全性是关键考虑因素,而且你愿意付出一些学习成本,那么 MapStruct 可能是一个更好的选择。如果你需要一个简单且易于使用的解决方案,并且性能要求不是很高,那么 Apache BeanUtils 或 Spring BeanUtils 可能是更合适的选择。

到此这篇关于Java中MapStruct入门使用及对比的文章就介绍到这了,更多相关Java MapStruct内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • IDEA下Maven的pom文件导入依赖出现Auto build completed with errors的问题

    IDEA下Maven的pom文件导入依赖出现Auto build completed with errors的问题

    这篇文章主要介绍了IDEA下Maven的pom文件导入依赖出现Auto build completed with errors,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • shiro整合springboot前后端分离

    shiro整合springboot前后端分离

    这篇文章主要介绍了shiro整合springboot前后端分离,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • 并发编程之Java内存模型锁的内存语义

    并发编程之Java内存模型锁的内存语义

    这篇文章主要介绍了并发编程之Java内存模型锁的内存语义,锁的作用是让临界区互斥执行,本文只要围绕锁的内存语义展开全文内容,需要的小伙伴可以参考一下
    2021-11-11
  • mybatis-generator生成文件覆盖问题的解决

    mybatis-generator生成文件覆盖问题的解决

    这篇文章主要介绍了mybatis-generator生成文件覆盖问题的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • SpringBoot响应Json数据乱码通过配置的解决

    SpringBoot响应Json数据乱码通过配置的解决

    这篇文章主要介绍了SpringBoot响应Json数据乱码通过配置的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • SpringMVC与Mybatis集合实现调用存储过程、事务控制实例

    SpringMVC与Mybatis集合实现调用存储过程、事务控制实例

    这篇文章主要介绍了SpringMVC与Mybatis集合实现调用存储过程、事务控制实例,有需要的可以了解一下。
    2016-11-11
  • spring boot启动加载数据原理分析

    spring boot启动加载数据原理分析

    实际应用中,我们会有在项目服务启动的时候就去加载一些数据或做一些事情这样的需求。这时spring Boot 为我们提供了一个方法,通过实现接口 CommandLineRunner 来实现。下面给大家详细介绍下,需要的的朋友参考下吧
    2017-04-04
  • Java使用Statement接口执行SQL语句操作实例分析

    Java使用Statement接口执行SQL语句操作实例分析

    这篇文章主要介绍了Java使用Statement接口执行SQL语句操作,结合实例形式详细分析了Java使用Statement接口针对mysql数据库进行连接与执行SQL语句增删改查等相关操作技巧与注意事项,需要的朋友可以参考下
    2018-07-07
  • Java多线程中的CountDownLatch详细解读

    Java多线程中的CountDownLatch详细解读

    这篇文章主要介绍了Java多线程中的CountDownLatch详细解读,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待,用给定的计数 初始化 CountDownLatch,需要的朋友可以参考下
    2023-11-11
  • Java实现bmp和jpeg图片格式互转

    Java实现bmp和jpeg图片格式互转

    本文主要介绍了Java实现bmp和jpeg图片格式互转,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04

最新评论