SpringBoot实战:整合MapStruct实现数据类型转化

news2025/1/11 16:42:58

MapStruct 是一个代码生成器,它基于约定优于配置方法极大地简化了 Java bean 类型之间映射的实现。自动生成的映射转换代码只使用简单的方法调用,因此速度快、类型安全而且易于理解阅读;本篇就是实现 SpringBoot 整合 MapStruct 实现数据类型转化。

项目源码实现前分支地址:https://toscode.gitee.com/li_ziheng/lizhengi-samples/tree/feature%2Fspring-boot-1.0.0/

项目源码实现后分支地址:https://toscode.gitee.com/li_ziheng/lizhengi-samples/tree/feature%2Fspring-boot-1.0.1/

本篇内容包括:项目介绍与条件准备、项目搭建与构造、效果验证


文章目录

    • 一、项目介绍与条件准备
        • 1、项目使用框架/模块介绍
        • 2、MapStruct 注释说明
        • 3、Idea 安装 MapStruct 插件
        • 3、项目结构说明
    • 二、项目搭建与构造
        • 1、添加项目 maven 依赖
        • 2、转换对象 DTO 与 VO
        • 3、转换器 Converter 实现
        • 4、相关工具类实现
        • 5、service 服务层调用
        • 6、controller 控制层实现
    • 三、效果验证


一、项目介绍与条件准备

1、项目使用框架/模块介绍

  • MapStruct:一个代码生成器,它基于约定优于配置方法极大地简化了 Java bean 类型之间映射的实现。自动生成的映射转换代码只使用简单的方法调用,因此速度快、类型安全而且易于理解阅读;
  • commons-lang3:apache 提供的众多 commons 工具包,号称 Java 第二 API,而 common 里面 lang3 包更是被我们使用得最多的。

2、MapStruct 注释说明

注解说明:

@Mapper 只有在接口加上这个注解, MapStruct 才会去实现该接口
    @Mapper 里有个 componentModel 属性,主要是指定实现类的类型,一般用到两个
    default:默认,可以通过 Mappers.getMapper(Class) 方式获取实例对象
    spring:在接口的实现类上自动添加注解 @Component,可通过 @Autowired 方式注入
@Mapping:属性映射,若源对象属性与目标对象名字一致,会自动映射对应属性
    source:源属性
    target:目标属性
    dateFormat:StringDate 日期之间相互转换,通过 SimpleDateFormat,该值为 SimpleDateFormat 的日期格式
    ignore: 忽略这个字段
@Mappings:配置多个@Mapping
@MappingTarget 用于更新已有对象
@InheritConfiguration 用于继承配置

3、Idea 安装 MapStruct 插件

Idea 可以安装以下 MapStruct 插件:

image-20221209020829864

3、项目结构说明

├── controller — 控制层(将请求通过 url 匹配,分配到不同的接收器/方法进行处理,然后返回结果)

├── service — 服务层接口

​ └── impl — 服务层实现

├── mapper — 数据访问层,与数据库交互为 service 提供接口

├── entity — 实体对象

​ ├── converter — 实体对象转换器

​ ├── dto — 持久层需要的实体对象(用于服务层与持久层之间的数据传输对象)

​ └── vo — 视图层需要的实体对象(用于服务层与视图层之间的数据传输对象)

├── utils — 工具类

└── Application.java — 入口启动类


二、项目搭建与构造

1、添加项目 maven 依赖

# 添加项目 maven 依赖,pom.xml 文件添加内容如下:

        <!--    数据类型转化工具 MapStruct    -->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <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>
        
        <!--    apache的 common-lang3 工具类    -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>

2、转换对象 DTO 与 VO

# DTO对象 Event-事件 持久层实体对象实现

package com.lizhengi.entity.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

/**
 * @author lizhengi
 * @version 1.0.0
 * @description Event-事件 持久层实体对象实现
 * @date 2022-12-07 3:59 下午
 **/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class EventDTO {

    /**
     * 事件ID
     */
    private Integer eventId;

    /**
     * 事件名称
     */
    private String eventName;

    /**
     * 事件类型
     */
    private String eventType;

    /**
     * 事件发生是否为精确时间 0大约/1精确
     */
    private Boolean eventIsAccurate;

    /**
     * 事件发生在公元前 0公元前/公元后
     */
    private Boolean eventIsBc;

    /**
     * 事件发生年份
     */
    private String eventYear;

    /**
     * 事件发生月份
     */
    private String eventMonth;

    /**
     * 事件发生日
     */
    private String eventDay;

    /**
     * 事件地点
     */
    private String eventLocation;

    /**
     * 事件人物
     *
     * @see CharacterDTO
     */
    private List<CharacterDTO> eventCharacters;

    /**
     * 事件描述
     */
    private String eventDescription;
}

# DTO对象 Character-人物 持久层实体对象实现

package com.lizhengi.entity.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author lizhengi
 * @version 1.0.0
 * @description Character-人物 持久层实体对象实现
 * @date 2022-12-07 4:40 下午
 **/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CharacterDTO {

    /**
     * 人物ID
     */
    private Integer characterId;

    /**
     * 人物名称
     */
    private String characterName;

    /**
     * 人物介绍
     */
    private String characterProfile;

    /**
     * 人物登场时间(负数表示公元前)
     */
    private Integer characterAppearanceDate;
}

# VO对象 Event-事件 视图层实体对象实现

package com.lizhengi.entity.vo;

import com.lizhengi.entity.dto.CharacterDTO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

/**
 * @author liziheng
 * @version 1.0.0
 * @description Event-事件 视图层实体对象实现
 * @date 2022-12-09 00:58 上午
 **/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class EventVO {

    /**
     * 事件名称
     */
    private String eventName;

    /**
     * 事件类型
     */
    private String eventType;

    /**
     * 事件发生时间
     */
    private String eventDate;

    /**
     * 事件地点
     */
    private String eventLocation;

    /**
     * 事件人物
     *
     * @see CharacterDTO
     */
    private List<CharacterVO> characters;

    /**
     * 事件描述
     */
    private String eventDescription;
}

# VO对象 Character-人物 视图层实体对象实现

package com.lizhengi.entity.vo;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author liziheng
 * @version 1.0.0
 * @description Character-人物 视图层实体对象实现
 * @date 2022-12-09 00:59 上午
 **/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CharacterVO {

    /**
     * 人物名称
     */
    private String name;

    /**
     * 人物介绍
     */
    private String profile;

    /**
     * 人物登场时间(负数表示公元前)
     */
    private Integer appearanceDate;
}

3、转换器 Converter 实现

# EventConverter抽象类 Event-事件 转换器

package com.lizhengi.entity.converter;

import com.lizhengi.entity.dto.EventDTO;
import com.lizhengi.entity.vo.EventVO;
import com.lizhengi.utils.DateUtil;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author liziheng
 * @version 1.0.0
 * @description Event-事件 转换器
 * @date 2022-12-09 1:01 上午
 **/
@Mapper(componentModel = "Spring")
public abstract class EventConverter {

    @Resource
    CharacterConverter characterConverter;

    /**
     * DTO 转 VO
     *
     * @param eventDTO EventDTO
     * @return EventVO
     */
    @Mappings({
            @Mapping(target = "eventDate", expression = "java(dto2voFieldEventDateConverter(eventDTO))"),
            @Mapping(target = "characters", expression = "java(characterConverter.dtoList2voList(eventDTO.getEventCharacters()))")
    })
    public abstract EventVO dto2vo(EventDTO eventDTO);

    /**
     * DTO 列表 转 VO 列表
     *
     * @param eventDTOList List<EventDTO>
     * @return List<EventVO>
     */
    public abstract List<EventVO> dtoList2voList(List<EventDTO> eventDTOList);

    /**
     * DTO 与 VO 间时间类型转换
     * @param eventDTO EventDTO
     * @return String
     */
    public String dto2voFieldEventDateConverter(EventDTO eventDTO) {
        return DateUtil.getEventDateByDateInfo(eventDTO.getEventIsAccurate(), eventDTO.getEventIsBc(),
                eventDTO.getEventYear(), eventDTO.getEventMonth(), eventDTO.getEventDay());
    }
}

# CharacterConverter接口 Character-人物 转换器

package com.lizhengi.entity.converter;

import com.lizhengi.entity.dto.CharacterDTO;
import com.lizhengi.entity.vo.CharacterVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;

import java.util.List;

/**
 * @author liziheng
 * @version 1.0.0 
 * @description Character-人物 转换器
 * @date 2022-12-09 2:27 上午
 **/
@Mapper(componentModel = "Spring")
public interface CharacterConverter {

    /**
     * DTO 转 VO
     *
     * @param characterDTO characterDTO
     * @return characterVO
     */
    @Mappings({
            @Mapping(target = "appearanceDate", source = "characterAppearanceDate"),
            @Mapping(target = "name", source = "characterName"),
            @Mapping(target = "profile", source = "characterProfile")
    })
    CharacterVO dto2vo(CharacterDTO characterDTO);

    /**
     * DTO 列表 转 VO 列表
     *
     * @param characterDTOList List<characterDTO>
     * @return List<characterVO>
     */
    List<CharacterVO> dtoList2voList(List<CharacterDTO> characterDTOList);
}

4、相关工具类实现

# 日期工具类

package com.lizhengi.utils;

import org.apache.commons.lang3.StringUtils;

/**
 * @author liziheng
 * @version 1.0.0
 * @description 日期工具类
 * @date 2022-12-09 2:20 上午
 **/
public class DateUtil {


    /**
     * 根据「事件时间信息」获取「事件时间概述」
     *
     * @param isAccurate 是否精确时间
     * @param isBc       是否为公元前
     * @param year       年份
     * @param month      月份
     * @param day        日
     * @return String
     */
    public static String getEventDateByDateInfo(Boolean isAccurate, Boolean isBc, String year, String month, String day) {

        StringBuilder builder = new StringBuilder();

        if (!isAccurate) {
            builder.append("约");
        }
        if (isBc) {
            builder.append("公元前");
        } else {
            builder.append("公元");
        }
        // 具体日期
        builder.append(year).append("年")
                .append(StringUtils.isBlank(month) ? "" : (month + "月"))
                .append((StringUtils.isBlank(month) || StringUtils.isBlank(day) ? "" : day + "日"));
        return String.valueOf(builder);
    }
}

5、service 服务层调用

# EventServiceImpl Event-事件 ServiceImpl

package com.lizhengi.service.impl;

import com.lizhengi.entity.converter.EventConverter;
import com.lizhengi.entity.vo.EventVO;
import com.lizhengi.mapper.EventMapper;
import com.lizhengi.service.EventService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author lizhengi
 * @version 1.0.0
 * @description Event-事件 ServiceImpl
 * @date 2022-12-07 8:14 下午
 **/
@Service
public class EventServiceImpl implements EventService {

    EventMapper mapper;

    @Autowired
    public void setMapper(EventMapper mapper) {
        this.mapper = mapper;
    }

    @Resource
    private EventConverter eventConverter;

    /**
     * 全量获取 EventDto 信息
     *
     * @return List<EventDTO>
     */
    @Override
    public List<EventVO> getEventDtoList(){
        // 使用 MapStruct 实现 DTO-VO 转换器
        return eventConverter.dtoList2voList(mapper.getEventDtoList());
    }

}

6、controller 控制层实现

# EventController

package com.lizhengi.controller;

import com.lizhengi.entity.vo.EventVO;
import com.lizhengi.service.impl.EventServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author liziheng
 * @version 1.0.0
 * @description Event-事件 Controller
 * @date 2022-12-07 8:17 下午
 **/
@RestController
@RequestMapping("/api/lizhengi/event")
public class EventController {

    EventServiceImpl eventService;

    @Autowired
    public void setEventService(EventServiceImpl eventService) {
        this.eventService = eventService;
    }

    @RequestMapping(path = {"/list"}, method = RequestMethod.GET)
    public List<EventVO> getEventDtoList(){
        return eventService.getEventDtoList();
    }

}

三、效果验证

使用 Postman 请求 ‘http://localhost:8080/api/lizhengi/event/list’ 接口,验证效果:

image-20221209025123636

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/75182.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]JAVA毕业设计小区物业管理系统演示录像2020(系统+LW)

[附源码]JAVA毕业设计小区物业管理系统演示录像2020&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09…

ffmpeg库安装及入门指南(Windows篇)- 2022年底钜献

最近项目需要&#xff0c;使用了 ffmpeg 做摄像头视频采集和串流。这几天有点时间&#xff0c;打算把相关的一些知识记录分享一下。 在撰写本文时&#xff0c;我又在另外一台电脑上把 ffmpeg 重新安装了一遍&#xff0c;所以绝对真实靠谱&#xff01;如果你觉得文章写得还不错…

代码效果测试

ROBUST TEXT DETECTION IN NATURAL IMAGES WITH EDGE ENHANCED MAXIMALLY STABLE EXTREMAL REGIONS 代码地址&#xff1a;https://github.com/akab/TextDetection 基本步骤&#xff1a; 1&#xff09;将原图转为灰度图&#xff1b; 2&#xff09;使用OpenCV的canny函数进行边…

HTML -- 常用标签及示例总结

文章目录HTML常用标签1 标签语义1.1 标签属性2 标题标签 h1 - h63 段落和换行标签3.1 段落标签3.2 换行标签4 文本格式化标签5 div和span6 图像标签7 超链接标签7.1 链接的语法格式7.2 链接分类8 表格标签8.1 表格的主要作用8.2 表格的基本语法8.3 表头单元格标签8.4 表格属性8…

C语言随机数的产生(rand、srand、time函数细节讲解)

✨C语言随机数的产生随机数生成代码&#xff1a;rand函数&#xff1a;srand函数&#xff1a;time函数&#xff1a;time函数补充:time_t类型讨论time_t指针传入的讨论&#xff1a;随机数生成代码&#xff1a; 先上代码&#xff0c;再详细解释&#xff1a; #include<stdio.h…

Python数组数据处理办法清单

import numpy as np import pandas as pd import matplotlib.pyplot as plt#matplotlib 的字体&#xff08;font&#xff09;为黑体&#xff08;SimHei&#xff09; plt.rcParams[font.sans-serif] [SimHei, ] # matplotlib正确显示正负号 plt.rcParams[axes.unicode_minus] …

dfs序(树形结构线性化)

dfs序是将树形结构转换为线性结构的一种方式。 dfs序 dfs序&#xff1a; 指每个节点在dfs深度优先遍历中的进出栈的时间序列。 定义三个数组&#xff1a; in[x]&#xff1a;表示结点x 入栈的时间戳。 out[x]&#xff1a;表示结点x出栈的时间戳&#xff0c;特殊的&#xff0c;出…

Linux网络原理及编程(5)——第十五节 TCP的连接(三次握手、四次挥手)

目录 三次握手 四次挥手 我们来重点说说两个状态&#xff1a;CLOSE_WAIT和TIME_WAIT 【CLOSE_WAIT】 【TIME_WAIT】 各位好&#xff0c;博主新建了个公众号《自学编程村》&#xff0c;拉到底部即可看到&#xff0c;有情趣可以关注看看哈哈&#xff0c;关注后还可以加博主w…

Linux CENTOS安装mysql8 64位

1. 查看系统中是否已经安装了mariadb 执行&#xff1a;yum list installed | grep mariadb 若已经存在&#xff0c;则删除 执行&#xff1a; yum remove mariadb 2.下载需要安装的压缩文件&#xff0c;从官网下载&#xff0c;文件为名字为 mysql-8.0.31-linux-glibc2.12-x86_6…

S7-1200和1500PLC与条码枪建立TCP_IP通信的具体方法示例

S7-1200和1500PLC与条码枪建立TCP_IP通信的具体方法示例 今天和大家分享西门子S7-1200和1500PLC如何获取条码枪的扫描数据,这种案例中一般PLC作为TCP/IP的客户端(只接收数据,不发送数据),条码枪作为TCP/IP的服务器。 如下图所示,在指令—通信—开放式用户通信中可以找到相关…

洞察 | 软件定义汽车时代下,汽车制造产业的应对策略

汽车产业作为先进制造行业&#xff0c;伴随着数字化技术&#xff0c;电气化技术的迭代正快速的成长&#xff0c;而随着智能汽车、自动驾驶概念的提出&#xff0c;整车制造的软硬件复杂度也在持续提升&#xff0c;软件定义汽车转型已成整体汽车制造产业的共识。 据中国软件行业…

成长任务| 挑战代码画颗圣诞树

&#x1f384;立即投稿&#x1f384; &#x1f4cc;活动规则 圣诞将至&#xff0c;这次来试试用代码过圣诞吧~挑战圣诞树的一万种画法! √ 使用代码画一颗#圣诞树#&#xff0c;将你的代码文件通过本页面投稿&#xff0c;审核通过即可参与活动 √ 可使用任意编程语言&#xff…

【解纠缠表示:图像增强】

DRLIE: Flexible Low-Light Image Enhancement via Disentangled Representations &#xff08;DRLIE&#xff1a;基于解纠缠表示的柔性弱光图像增强&#xff09; 解纠缠表示 弱光图像增强&#xff08;Low-light image enhancement (LIME)&#xff09;是将亮度不理想的图像转化…

为了彻底弄懂CSS中的1px究竟有多长,我翻出了家里的卷尺

CSS是描述HTML文档如何显示的&#xff0c;在显示的过程中&#xff0c;HTML元素的长宽、间距、字体大小等等&#xff0c;都需要通过长度尺寸单位来表示。我们常常会说&#xff1a;字体大小16像素&#xff0c; 间距10个像素。这里的像素&#xff0c;就是CSS中的长度尺寸单位。一个…

软件测试行业真的不行了吗?那出路到底在哪?

下面这张图片&#xff0c;想必大家应该都知道~~~ 其实每个人都在金字塔里面&#xff0c;只不过大家的高低位置不同&#xff0c;当然&#xff0c;越在底层的人越多&#xff0c;越在高层的人越少~ 这也符合“二八定律”&#xff0c;“优胜劣汰”&#xff0c;“适者生存”~ 当你的…

c++中的this指针

1.this指针的引入 首先我们看下面这一段代码 class Date { public:void DateSet(int year, int month, int day){_year year;_month month;_day day;}void print(){cout << _year << "-" << _month << "-" << _day <…

论文速递:一种用于视觉定位的基于NLP思路的直线特征匹配算法

标题&#xff1a;Line as a Visual Sentence:Context-aware Line Descriptor for Visual Localization 作者&#xff1a;Sungho Yoon1 and Ayoung Kim2∗ 摘要 在机器人以及计算机视觉领域&#xff0c;除了通过使用图像匹配的特征点计算多视图几何来求解问题&#xff0c;还可…

12月的第一波驱动,来看看支持哪款游戏吧!

真的停不下来&#xff01;2022年的最后一个月&#xff0c;新游戏仍然在发力&#xff0c;《极品飞车&#xff1a;不羁》、《巫师 3&#xff1a;狂猎》、《传送门RTX版》都在12月正式上线&#xff01; 为了提供更好的游戏体验&#xff0c;英伟达、AMD、英特尔三巨头更是马不停蹄…

时间轮算法HashedWheelTimer

文章目录一.HashedWheelTimer是什么?二.能干什么?为什么需要这个东西?优点适用场景三.怎么用?使用步骤1.引入pom2.使用举例四.时间轮原理五.使用注意点1.一个HashedWheelTimer对象只有一个worker线程2.每次添加的任务只会执行一次3.时间轮的参数非常重要4.所有的任务都是顺…

rabbitmq基础1——消息中间件概念、Rabbitmq的发展起源和基本组件的作用流程

文章目录一、消息中间件1.1 概念1.2 作用1.2.1 消息队列持久化1.2.2 消息队列分发策略1.2.3 消息队列的高可用和高可靠1.2.3.1 一主多从共享集群1.2.3.2 一主多从同步集群1.2.3.3 多主多从同步集群1.2.3.4 多主转发集群1.2.3.5 Master-slave与Breoker-cluster组合方案1.3 初识A…