Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >第三十章:SpringBoot使用MapStruct自动映射DTO

第三十章:SpringBoot使用MapStruct自动映射DTO

作者头像
恒宇少年
发布于 2018-06-27 07:49:14
发布于 2018-06-27 07:49:14
5.4K00
代码可运行
举报
运行总次数:0
代码可运行

MapStruct是一种类型安全的bean映射类生成java注释处理器。

我们要做的就是定义一个映射器接口,声明任何必需的映射方法。在编译的过程中,MapStruct会生成此接口的实现。该实现使用纯java方法调用的源和目标对象之间的映射,MapStruct节省了时间,通过生成代码完成繁琐和容易出错的代码逻辑。下面我们来揭开它的神秘面纱

本章目标

基于SpringBoot平台完成MapStruct映射框架的集成。

SpringBoot 企业级核心技术学习专题

专题

专题名称

专题描述

001

Spring Boot 核心技术

讲解SpringBoot一些企业级层面的核心组件

002

Spring Boot 核心技术章节源码

Spring Boot 核心技术简书每一篇文章码云对应源码

003

Spring Cloud 核心技术

对Spring Cloud核心技术全面讲解

004

Spring Cloud 核心技术章节源码

Spring Cloud 核心技术简书每一篇文章对应源码

005

QueryDSL 核心技术

全面讲解QueryDSL核心技术以及基于SpringBoot整合SpringDataJPA

006

SpringDataJPA 核心技术

全面讲解SpringDataJPA核心技术

构建项目

我们使用idea开发工具创建一个SpringBoot项目,添加相应的依赖,pom.xml配置文件如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...省略部分代码
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <org.mapstruct.version>1.2.0.CR1</org.mapstruct.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <!--<scope>provided</scope>-->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--mapStruct依赖-->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-jdk8</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${org.mapstruct.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
        
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.31</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
....省略部分代码

集成MapStruct官方提供了两种方式,上面配置文件内我们采用的是直接添加Maven依赖,而官方文档还提供了另外一种方式,采用Maven插件形式配置,配置如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...引用官方文档
...
<properties>
    <org.mapstruct.version>1.2.0.CR1</org.mapstruct.version>
</properties>
...
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-jdk8</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
</dependencies>
...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>
...

我个人比较喜欢采用第一种方式,不需要配置过多的插件,依赖方式比较方便。

接下来我们开始配置下数据库连接信息以及简单的两张表的SpringDataJPA相关接口。

数据库连接信息

在resource下新创建一个application.yml文件,并添加如下数据库连接配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8
    username: root
    password: 123456
    #最大活跃数
    maxActive: 20
    #初始化数量
    initialSize: 1
    #最大连接等待超时时间
    maxWait: 60000
    #打开PSCache,并且指定每个连接PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    #通过connectionProperties属性来打开mergeSql功能;慢SQL记录
    #connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
    minIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 1 from dual
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    #配置监控统计拦截的filters,去掉后监控界面sql将无法统计,'wall'用于防火墙
    filters: stat, wall, log4j
  jpa:
    properties:
      hibernate:
        show_sql: true
        format_sql: true

有关SpringDataJPA相关的学习请访问第三章:SpringBoot使用SpringDataJPA完成CRUD,我们在数据库内创建两张表信息分别是商品基本信息表、商品类型表。

两张表有相应的关联,我们在不采用连接查询的方式模拟使用MapStruct,表信息如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
--商品类型信息表
CREATE TABLE `good_types` (
  `tgt_id` int(11) NOT NULL AUTO_INCREMENT,
  `tgt_name` varchar(30) DEFAULT NULL,
  `tgt_is_show` int(1) DEFAULT NULL,
  `tgt_order` int(255) DEFAULT NULL,
  PRIMARY KEY (`tgt_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

--商品基本信息表
CREATE TABLE `good_infos` (
  `tg_id` int(11) NOT NULL AUTO_INCREMENT,
  `tg_type_id` int(11) DEFAULT NULL,
  `tg_title` varchar(30) DEFAULT NULL,
  `tg_price` decimal(8,2) DEFAULT NULL,
  `tg_order` int(2) DEFAULT NULL,
  PRIMARY KEY (`tg_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

INSERT INTO `good_types` VALUES ('1', '青菜', '1', '1');
INSERT INTO `good_infos` VALUES ('1', '1', '芹菜', '12.40', '1');

下面我们根据这两张表创建对应的实体类。

商品类型实体
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.yuqiyu.chapter30.bean;

import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * ========================
 * Created with IntelliJ IDEA.
 * User:恒宇少年
 * Date:2017/8/20
 * Time:11:17
 * 码云:http://git.oschina.net/jnyqy
 * ========================
 */
@Entity
@Table(name = "good_types")
@Data
public class GoodTypeBean
{
    @Id
    @Column(name = "tgt_id")
    private Long id;

    @Column(name = "tgt_name")
    private String name;
    @Column(name = "tgt_is_show")
    private int show;
    @Column(name = "tgt_order")
    private int order;

}
商品基本信息实体
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.yuqiyu.chapter30.bean;

import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * ========================
 * Created with IntelliJ IDEA.
 * User:恒宇少年
 * Date:2017/8/20
 * Time:11:16
 * 码云:http://git.oschina.net/jnyqy
 * ========================
 */
@Entity
@Table(name = "good_infos")
@Data
public class GoodInfoBean
{
    @Id
    @Column(name = "tg_id")
    private Long id;
    @Column(name = "tg_title")
    private String title;
    @Column(name = "tg_price")
    private double price;
    @Column(name = "tg_order")
    private int order;
    @Column(name = "tg_type_id")
    private Long typeId;
}

接下来我们继续创建相关的JPA。

商品类型JPA
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.yuqiyu.chapter30.jpa;

import com.yuqiyu.chapter30.bean.GoodTypeBean;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * ========================
 * Created with IntelliJ IDEA.
 * User:恒宇少年
 * Date:2017/8/20
 * Time:11:24
 * 码云:http://git.oschina.net/jnyqy
 * ========================
 */
public interface GoodTypeJPA
    extends JpaRepository<GoodTypeBean,Long>
{
}
商品信息JPA
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.yuqiyu.chapter30.jpa;

import com.yuqiyu.chapter30.bean.GoodInfoBean;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * ========================
 * Created with IntelliJ IDEA.
 * User:恒宇少年
 * Date:2017/8/20
 * Time:11:23
 * 码云:http://git.oschina.net/jnyqy
 * ========================
 */
public interface GoodInfoJPA
    extends JpaRepository<GoodInfoBean,Long>
{
    
}

配置MapStruct

到目前为止我们的准备工作差不多完成了,下面我们开始配置使用MapStruct。我们的最终目的是为了返回一个自定义的DTO实体,那么我们就先来创建这个DTO,DTO的代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.yuqiyu.chapter30.dto;

import lombok.Data;

/**
 * 转换Dto
 * ========================
 * Created with IntelliJ IDEA.
 * User:恒宇少年
 * Date:2017/8/20
 * Time:11:25
 * 码云:http://git.oschina.net/jnyqy
 * ========================
 */
@Data
public class GoodInfoDTO
{
    //商品编号
    private String goodId;
    //商品名称
    private String goodName;
    //商品价格
    private double goodPrice;
    //类型名称
    private String typeName;
}

可以看到GoodInfoDTO实体内集成了商品信息、商品类型两张表内的数据,对应查询出信息后,我们需要使用MapStruct自动映射到GoodInfoDTO。

创建Mapper

Mapper这个定义一般是被广泛应用到MyBatis半自动化ORM框架上,而这里的Mapper跟Mybatis没有关系。下面我们先来看下代码,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.yuqiyu.chapter30.mapper;

import com.yuqiyu.chapter30.bean.GoodInfoBean;
import com.yuqiyu.chapter30.bean.GoodTypeBean;
import com.yuqiyu.chapter30.dto.GoodInfoDTO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;

/**
 * 配置映射
 * ========================
 * Created with IntelliJ IDEA.
 * User:恒宇少年
 * Date:2017/8/20
 * Time:11:26
 * 码云:http://git.oschina.net/jnyqy
 * ========================
 */
@Mapper(componentModel = "spring")
//@Mapper
public interface GoodInfoMapper
{
    //public static GoodInfoMapper MAPPER = Mappers.getMapper(GoodInfoMapper.class);

    @Mappings({
            @Mapping(source = "type.name",target = "typeName"),
            @Mapping(source = "good.id",target = "goodId"),
            @Mapping(source = "good.title",target = "goodName"),
            @Mapping(source = "good.price",target = "goodPrice")
    })
    public GoodInfoDTO from(GoodInfoBean good, GoodTypeBean type);
}

可以看到GoodInfoMapper是一个接口的形式存在的,当然也可以是一个抽象类,如果你需要在转换的时候才用个性化的定制的时候可以采用抽象类的方式,相应的代码配置官方文档已经声明。

@Mapper注解是用于标注接口、抽象类是被MapStruct自动映射的标识,只有存在该注解才会将内部的接口方法自动实现。

MapStruct为我们提供了多种的获取Mapper的方式,比较常用的两种分别是

默认配置

默认配置,我们不需要做过多的配置内容,获取Mapper的方式就是采用Mappers通过动态工厂内部反射机制完成Mapper实现类的获取。

默认方式获取Mapper如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Mapper接口内部定义
public static GoodInfoMapper MAPPER = Mappers.getMapper(GoodInfoMapper.class);

//外部调用
GoodInfoMapper.MAPPER.from(goodBean,goodTypeBean);
Spring方式配置

Spring方式我们需要在@Mapper注解内添加componentModel属性值,配置后在外部可以采用@Autowired方式注入Mapper实现类完成映射方法调用。

Spring方式获取Mapper如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//注解配置
@Mapper(componentModel = "spring")

//注入Mapper实现类
@Autowired
private GoodInfoMapper goodInfoMapper;

//调用
goodInfoMapper.from(goodBean,goodTypeBean);
@Mappings & @Mapping

Mapper接口定义方法上面声明了一系列的注解映射@Mapping以及@Mappings,那么这两个注解是用来干什么工作的呢?

@Mapping注解我们用到了两个属性,分别是sourcetarget

source代表的是映射接口方法内的参数名称,如果是基本类型的参数,参数名可以直接作为source的内容,如果是实体类型,则可以采用实体参数名.字段名的方式作为source的内容,配置如上面GoodInfoMapper内容所示。

target代表的是映射到方法方法值内的字段名称,配置如上面GoodInfoMapper所示。

查看Mapper实现

下面我们执行maven compile命令,到target/generated-sources/annotations目录下查看对应Mapper实现类,实现类代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.yuqiyu.chapter30.mapper;

import com.yuqiyu.chapter30.bean.GoodInfoBean;
import com.yuqiyu.chapter30.bean.GoodTypeBean;
import com.yuqiyu.chapter30.dto.GoodInfoDTO;
import javax.annotation.Generated;
import org.springframework.stereotype.Component;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2017-08-20T12:52:52+0800",
    comments = "version: 1.2.0.CR1, compiler: javac, environment: Java 1.8.0_111 (Oracle Corporation)"
)
@Component
public class GoodInfoMapperImpl implements GoodInfoMapper {

    @Override
    public GoodInfoDTO from(GoodInfoBean good, GoodTypeBean type) {
        if ( good == null && type == null ) {
            return null;
        }

        GoodInfoDTO goodInfoDTO = new GoodInfoDTO();

        if ( good != null ) {
            if ( good.getId() != null ) {
                goodInfoDTO.setGoodId( String.valueOf( good.getId() ) );
            }
            goodInfoDTO.setGoodName( good.getTitle() );
            goodInfoDTO.setGoodPrice( good.getPrice() );
        }
        if ( type != null ) {
            goodInfoDTO.setTypeName( type.getName() );
        }

        return goodInfoDTO;
    }
}

MapStruct根据我们配置的@Mapping注解自动将source实体内的字段进行了调用target实体内字段的setXxx方法赋值,并且做出了一切参数验证。

我们采用了Spring方式获取Mapper,在自动生成的实现类上MapStruct为我们自动添加了@ComponentSpring声明式注入注解配置。

运行测试

下面我们来创建一个测试的Controller,用于访问具体请求地址时查询出商品的基本信息以及商品的类型后调用GoodInfoMapper.from(xxx,xxx)方法完成返回GoodInfoDTO实例。Controller代码实现如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.yuqiyu.chapter30.controller;

import com.yuqiyu.chapter30.bean.GoodInfoBean;
import com.yuqiyu.chapter30.bean.GoodTypeBean;
import com.yuqiyu.chapter30.dto.GoodInfoDTO;
import com.yuqiyu.chapter30.jpa.GoodInfoJPA;
import com.yuqiyu.chapter30.jpa.GoodTypeJPA;
import com.yuqiyu.chapter30.mapper.GoodInfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 测试控制器
 * ========================
 * Created with IntelliJ IDEA.
 * User:恒宇少年
 * Date:2017/8/20
 * Time:12:24
 * 码云:http://git.oschina.net/jnyqy
 * ========================
 */
@RestController
public class GoodInfoController
{
    /**
     * 注入商品基本信息jpa
     */
    @Autowired
    private GoodInfoJPA goodInfoJPA;
    /**
     * 注入商品类型jpa
     */
    @Autowired
    private GoodTypeJPA goodTypeJPA;
    /**
     * 注入mapStruct转换Mapper
     */
    @Autowired
    private GoodInfoMapper goodInfoMapper;

    /**
     * 查询商品详情
     * @param id
     * @return
     */
    @RequestMapping(value = "/detail/{id}")
    public GoodInfoDTO detail(@PathVariable("id") Long id)
    {
        //查询商品基本信息
        GoodInfoBean goodInfoBean = goodInfoJPA.findOne(id);
        //查询商品类型基本信息
        GoodTypeBean typeBean = goodTypeJPA.findOne(goodInfoBean.getTypeId());
        //返回转换dto
        return goodInfoMapper.from(goodInfoBean,typeBean);
    }
}

在Controller内我们注入了GoodInfoJPAGoodTypeJPA以及GoodInfoMapper,在查询商品详情方法时做出了映射处理。接下来我们启动项目访问地址http://127.0.0.1:8080/detail/1查看界面输出效果,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
goodId: "1",
goodName: "芹菜",
goodPrice: 12.4,
typeName: "青菜"
}

可以看到界面输出了GoodInfoDTO内的所有字段内容,并且通过from方法将对应配置的target字段赋值。

总结

本章主要讲述了基于SpringBoot开发框架上集成MapStruct自动映射框架,完成模拟多表获取数据后将某一些字段通过@Mapping配置自动映射到DTO实体实例指定的字段内。

MapStruct官方文档地址:http://mapstruct.org/documentation/dev/reference/html/

本章代码已经上传到码云:

SpringBoot配套源码地址:https://gitee.com/hengboy/spring-boot-chapter

SpringCloud配套源码地址:https://gitee.com/hengboy/spring-cloud-chapter

SpringBoot相关系列文章请访问:目录:SpringBoot学习目录

QueryDSL相关系列文章请访问:QueryDSL通用查询框架学习目录

SpringDataJPA相关系列文章请访问:目录:SpringDataJPA学习目录

感谢阅读!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.08.20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
第五章:使用QueryDSL与SpringDataJPA实现查询返回自定义对象
在我们实际项目开发中,往往会遇到一种多表关联查询并且仅需要返回多表内的几个字段最后组合成一个集合或者实体。这种情况在传统的查询中我们无法控制查询的字段,只能全部查询出后再做出分离,这种也是我们最不愿意看到的处理方式,这种方式会产生繁琐、复杂、效率低、代码阅读性差等等问题。QueryDSL为我们提供了一个返回自定义对象的工具类型,而Java8新特性Collection中stream方法也能够完成返回自定义对象的逻辑,下面我们就来看下这两种方式如何编写? 本章目标 基于SpringBoot平台完成SpringD
恒宇少年
2018/06/27
4.7K0
第七章:使用QueryDSL与SpringDataJPA实现子查询
在上一章我们讲到了QueryDSL的聚合函数,让我们重新认识了QueryDSL的便利之处,它可以很好的使用原生SQL的思想来进行Java形式的描述,编写完成也不需要考虑更换数据库存在的不兼容问题。当然QueryDSL还有很多我们没有发掘出来的核心技术,我们今天来讲解下”子查询“,看看QueryDSL是怎么完美的诠释了使用Java写SQL。 本章目标 基于SpringBoot平台完成QueryDSL整合JPA实现多表、单表子查询。 构建项目 我们使用idea工具创建一个SpringBoot项目,然后添加部分依
恒宇少年
2018/06/27
5.3K0
第三十五章:SpringBoot与单元测试的小秘密
单元测试对于开发人员来说是非常熟悉的,我们每天的工作也都是围绕着开发与测试进行的,在最早的时候测试都是采用工具Debug模式进行调试程序,后来Junit的诞生也让程序测试发生了很大的变化。我们今天来讲解下基于SpringBoot结合Junit怎么来完成单元测试。 本章目的 基于SpringBoot平台整合Junit分别完成客户端、服务端的单元测试。 SpringBoot 企业级核心技术学习专题 专题 专题名称 专题描述 001 Spring Boot 核心技术 讲解SpringBoot一些企业级层面的核心组
恒宇少年
2018/06/27
1.4K0
第四十四章: 基于SpringBoot & AOP完成统一资源自动查询映射
本章内容比较偏向系统设计方面,简单的封装就可以应用到系统中使用,从而提高我们的编码效率以及代码的可读性。统一资源在系统内是不可避免的模块,资源分类也有很多种,比较常见如:图片资源、文本资源、视频资源等,那么资源统一处理的好处是什么呢?大家有可能会有疑问,我把资源存放到业务表内岂不更好吗?这样查询起来也方便,并不需要关联资源信息表!当然设计不分好坏,只有更适合、更简单!接下来带着疑问进入本章的内容。 本章目标 基于SpringBoot平台结合AOP完成统一资源的自动查询映射。 构建项目 本章使用到的依赖相对来
恒宇少年
2018/06/27
1.5K0
第三十九章:基于SpringBoot & Quartz完成定时任务分布式单节点持久化
定时任务在企业项目比较常用到,几乎所有的项目都会牵扯该功能模块,定时任务一般会处理指定时间点执行某一些业务逻辑、间隔时间执行某一些业务逻辑等。我们在之前有讲过SpringBoot是已经集成了定时任务的,详见:第二十六章:SpringBoot使用@Scheduled创建定时任务,那么我们本章将会采用外置的quartz定时任务框架来完成定时任务的分布式单节点持久化,我们为什么要持久化定时任务呢? 在一些项目中定时任务可能是必不可少的,由于某种特殊的原因定时任务可能丢失,如重启定时任务服务项目后,原内存中的定时任
恒宇少年
2018/06/27
2.4K0
第三十八章:基于SpringBoot架构使用Profile完成打包环境分离
在中大型企业项目开发中,环境分离是必不可少的一步,然而现在的开发人员也只是有这个概念,还是有很多项目采用普通的方式,每次打包发布部署的时候改动一大堆的配置文件,有一个地方忘记改就相当于白更新了一次系统,这种修改配置文件完成环境更换的方式给我们带来了很多的困扰,浪费了我们很多宝贵的时间!早在Spring 3.1版本就已经为我们提供了环境分离的相关注解配置方式,不过在传统的Spring项目中配置Profile确实有点麻烦,在Spring版本的不断更新直到后来SpringBoot成长起来后Profile已经能够很
恒宇少年
2018/06/27
6560
第四章:使用QueryDSL与SpringDataJPA实现多表关联查询
对于业务逻辑复制的系统来说都存在多表关联查询的情况,查询的返回对象内容也是根据具体业务来处理的,我们本章主要是针对多表关联根据条件查询后返回单表对象,在下一章我们就会针对多表查询返回自定义的对象实体。 本章目标 基于SpringBoot框架平台完成SpringDataJPA与QueryDSL多表关联查询返回单表对象实例,查询时完全采用QueryDSL语法进行编写。 构建项目 我们使用idea工具先来创建一个SpringBoot项目,添加的依赖跟第三章:使用QueryDSL与SpringDataJPA完成Up
恒宇少年
2018/06/27
3.3K0
第二章:使用QueryDSL与SpringDataJPA实现单表普通条件查询
在企业开发中ORM框架有很多种如:Hibernate,Mybatis,JdbcTemplate等。每一种框架的设计理念是不一样的,Hibernate跟我们本章讲解的SpringDataJPA是一致的框架都是全自动理念作为设计核心,让用户更少的去写SQL语句通过简单的配置就可以实现各种查询。而Mybatis框架则是半自动理念作为设计核心,SQL让用户自己定义实现了更好的灵活性。 本章目标 本章我们目标实现QueryDSL通用查询语言整合SpringDataJPA完成单表的查询多样化。 构建项目 下面我们先来创
恒宇少年
2018/06/27
1.7K0
第三十七章:基于SpringBoot架构以及参数装载完成接口安全认证
在上一章第三十六章:基于SpringBoot架构重写SpringMVC请求参数装载中我们说到了怎么去重写SpringMVC参数装载,从而来完成我们的需求。本章内容会在上一章的基础上进行修改! 企业中接口编写是再频繁不过的事情了,现在接口已经不仅仅用于移动端来做数据服务了,一些管理平台也同样采用了这种方式来完成前后完全分离的模式。不管是接口也好、分离模式也好都会涉及到数据安全的问题,那我们怎么可以很好的避免我们的数据参数暴露呢? 本章目标 基于SpringBoot平台实现参数安全传输。 SpringBoot
恒宇少年
2018/06/27
1.5K0
第二十七章:SpringBoot使用ApplicationEvent&Listener完成业务解耦
ApplicationEvent以及Listener是Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式,设计初衷也是为了系统业务逻辑之间的解耦,提高可扩展性以及可维护性。事件发布者并不需要考虑谁去监听,监听具体的实现内容是什么,发布者的工作只是为了发布事件而已。 我们平时日常生活中也是经常会有这种情况存在,如:我们在平时拔河比赛中,裁判员给我们吹响了开始的信号,也就是给我们发布了一个开始的事件,而拔河双方人员都在监听着这个事件,一旦事件发布后双方人员就开始往自己方使劲。而裁判
恒宇少年
2018/06/27
1.1K0
第二十八章:SpringBoot使用AutoConfiguration自定义Starter
在我们学习SpringBoot时都已经了解到starter是SpringBoot的核心组成部分,SpringBoot为我们提供了尽可能完善的封装,提供了一系列的自动化配置的starter插件,我们在使用spring-boot-starter-web时只需要在pom.xml配置文件内添加依赖就可以了,我们之前传统方式则是需要添加很多相关SpringMVC配置文件。而spring-boot-starter-web为我们提供了几乎所有的默认配置,很好的降低了使用框架时的复杂度。 因此在使用xx.starter时
恒宇少年
2018/06/27
1.5K0
第六章:使用QueryDSL的聚合函数
在企业级项目开发过程中,往往会经常用到数据库内的聚合函数,一般ORM框架应对这种逻辑问题时都会采用编写原生的SQL来处理,而QueryDSL完美的解决了这个问题,它内置了SQL所有的聚合函数下面我们简
恒宇少年
2018/06/27
3.7K0
第三十六章:基于SpringBoot架构重写SpringMVC请求参数装载
在国内企业开发项目中大多数都已经偏向Spring家族式的开发风格,在前几年国内项目都是以Structs2作为Web开发的主导,不过由于近几年发生的事情确实让开发者对它失去了以往的信心。与此同时Spring家族发布了SpringMVC,而且完美的整合Spring来开发企业级大型Web项目。它有着比Structs2更强大的技术支持以及更灵活的自定义配置,接下来我们就看看本章的内容,我们自定义实现SpringMVC参数绑定规则,根据业务定制参数装载实现方式。 本章目标 根据项目定制SpringMVC参数状态并了解
恒宇少年
2018/06/27
1.4K0
第四十五章:基于SpringBoot 设计业务逻辑异常统一处理
在我们平时的项目研发过程中,异常一般都是程序员最为头疼的问题,异常的抛出、捕获、处理等既涉及事务回滚,还会涉及返回前端消息提醒信息。那么我们怎么设计可以解决上面的两个的痛点呢?我们可不可以统一处理业务逻辑然后给出前端对应的异常提醒内容呢? 本章目标 基于SpringBoot平台构建业务逻辑异常统一处理,异常消息内容格式化。 SpringBoot 企业级核心技术学习专题 专题 专题名称 专题描述 001 Spring Boot 核心技术 讲解SpringBoot一些企业级层面的核心组件 002 Spri
恒宇少年
2018/06/27
1.8K0
第二十九章:基于SpringBoot平台使用Lombok来优雅的编码
Lombok对于Java偷懒开发者来说应该是比较中意的,恰恰笔者就是一个喜欢在小细节上偷懒来提高开发效率的人。所以在技术框架的海洋里寻找了很久才在GitHub开源平台上找到,而在这之前国外很多程序猿一直使用该框架了,Lombok框架提供了很多编码遍历,但是也降低了代码的阅读力。下面我们看看在Idea开发工具中该怎么使用Lombok? 本章目标 使用Lombok提高开发效率。 SpringBoot 企业级核心技术学习专题 专题 专题名称 专题描述 001 Spring Boot 核心技术 讲解SpringBo
恒宇少年
2018/06/27
6040
第三十四章:SpringBoot配置类WebMvcConfigurerAdapter
WebMvcConfigurerAdapter配置类其实是Spring内部的一种配置方式,采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制,下面我们来看一下该类内的常用方法。 本章目标 继承WebMvcConfigurerAdapter采用JavaBean形式实现个性化配置定制。 SpringBoot 企业级核心技术学习专题 专题 专题名称 专题描述 001 Spring Boot 核心技术 讲解SpringBoot一些企业级层面的核心组件 002 Spring Boot 核心
恒宇少年
2018/06/27
1.4K0
第四十一章: 基于SpringBoot & RabbitMQ完成DirectExchange分布式消息消费
消息队列目前流行的有KafKa、RabbitMQ、ActiveMQ等,它们的诞生无非不是为了解决消息的分布式消费,完成项目、服务之间的解耦动作。消息队列提供者与消费者之间完全采用异步通信方式,极力的提高了系统的响应能力,从而提高系统的网络请求吞吐量。 每一种的消息队列都有它在设计上的独一无二的优势,在实际的项目技术选型时根据项目的需求来确定。 本章目标 基于SpringBoot项目整合RabbitMQ消息队列,完成DirectExchange(路由键)分布式消息消费。 SpringBoot 企业级核心技术
恒宇少年
2018/06/27
1.3K0
第五十章:SpringBoot2.0新特性 - 岂止至今最简单redis缓存集成
自从SpringBoot升级到了2.0版本后集成Redis作为缓存就更为简单了,我们只需要配置Redis相关的链接信息以及使用注解@EnableCaching开启缓存,这样我们就直接可以在项目内使用缓存相关的内容。 由于最近这段时间一直在研发公司的持久化封装框架,用于编写文章的时间比较少,还请大家见谅,不过还会持续更新SpringBoot以及SpringCloud等系列文章,敬请期待!!! 本章目标 基于SpringBoot2完成快速集成Reids作为项目缓存,并讲解一些缓存常用的配置。 Spring
恒宇少年
2018/06/27
8280
SpringBoot 整合mapstruct|赶紧丢掉BeanUtils吧
代码已经上传到码云:https://gitee.com/lezaiclub/springboot-hyper-integration.git,欢迎白嫖
AI码师
2022/09/19
1.6K0
SpringBoot 整合mapstruct|赶紧丢掉BeanUtils吧
超详细 mapstruct 简化教程
MapStruct 结合spring使用,设定componentModel = "spring"即可,如下Mapper接口:
派大星在吗
2021/12/16
2.9K0
推荐阅读
相关推荐
第五章:使用QueryDSL与SpringDataJPA实现查询返回自定义对象
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验