SpringBoot3.0 + RocketMq 构建企业级数据中台「完JIE」

141 阅读4分钟

SpringBoot3.0 + RocketMq 构建企业级数据中台

// 下栽ke呈:ukoou.com/resource/1554

JavaBean 问题引入在开发的时候经常会有业务代码之间有很多的 JavaBean 之间的相互转化,比如PO/DTO/VO/QueryParam之间的转换问题。 之前我们的做法是:拷贝技术rg.apache.commons.beanutils.PropertyUtils.copyPropertiesorg.apache.commons.beanutils.BeanUtils.copyPropertiesorg.springframework.beans.BeanUtils.copyPropertiesnet.sf.cglib.beans.BeanCopier纯get/set辅助IDE插件拷贝对象时可以自动set所有方法字段 (这种方式可能有些开发人员不清楚)不仅看上去冗余添加新的字段时依然需要手动开发效率比较低# MapStruct 带来的改变MapSturct 是一个生成类型安全, 高性能且无依赖的 JavaBean 映射代码的注解处理器(annotation processor)。 工具可以帮我们实现 JavaBean 之间的转换, 通过注解的方式。

同时, 作为一个工具类,相比于手写, 其应该具有便捷, 不容易出错的特点。

MapStruct入门例子这里展示最基本的PO转VO的例子,使用的是IDEA + Lombok + MapStruct# Pom.xml注意:基于当前IDEA设置并不需要mapstruct-processor的依赖一般来说会加载两个包:org.mapstruct:mapstruct: 包含Mapstruct核心,比如注解等;如果是mapstruct-jdk8会引入一些jdk8的语言特性;org.mapstruct:mapstruct-processor: 处理注解用的,可以根据注解自动生成mapstruct的mapperImpl类如下示例基于IDEA实现,

可以在 build阶段的annotationProcessorPaths中配置mapstruct-processor的path。jar

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <org.mapstruct.version>1.4.0.Beta3</org.mapstruct.version>
    <org.projectlombok.version>1.18.12</org.projectlombok.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>

    <!-- lombok dependencies should not end up on classpath -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${org.projectlombok.version}</version>
        <scope>provided</scope>
    </dependency>

    <!-- fastjson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.71</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <pluginManagement>
        <plugins>
            <plugin>

自定义注解实现 Spring Boot动态多数据源--数据源创建

一、引入依赖

****引入数据库连接池的依赖——druid和面向切面编程的依赖——aop,如下所示:

**

        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.21</version>
        </dependency>
        <!-- aop -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

二、创建数据库

  1、主数据库

  使用前文中已经创建的名为spring_boot_demo的数据库。

  spring_boot_demo中t_user数据如下:

  

  2、辅数据库

  数据库名为other_data,库中建立数据表t_user,表结构与spring_boot_demo中的t_user一致。

  实际项目中,大多是跨数据库的数据源切换,常用在同公司的多个不同系统中共用一个用户数据库,或者二次开发项目在原有数据库基础上做拓展,保留原有的数据连接。

这里为了方便操作,就都在mysql下部署数据库并且使表结构一致,方便形成数据对比。

  other_data中插入数据如下:

  

三、修改数据库连接配置信息

  在application.yml中,修改数据库连接配置如下:

**

spring:
  application:
    name: spring-boot-demo
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      primary:
        url: jdbc:mysql://localhost:3306/spring_boot_demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT%2B8
        username: root
        password: root
        driverClassName: com.mysql.jdbc.Driver
      second:
        url: jdbc:mysql://localhost:3306/other_data?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT%2B8
        username: root
        password: root
        driverClassName: com.mysql.jdbc.Driver

  

四、编写代码

结构如下:

  1、枚举类DataSourceName:

  该类用来存放数据源的名称,定义两个数据源名称分别为PRIMARYSECOND

**

package com.example.demo.enums;

/**
 * DataSource的name常量
 * 便于切换
 * @author 我命倾尘
 */
public enum DataSourceName {

    /**
     * 主数据源 spring_boot_demo
     */
    PRIMARY("PRIMARY"),

    /**
     * 副数据源other_data
     */
    SECOND("SECOND");

    private String dataSourceName;
    private DataSourceName(String dataSourceName){
        this.dataSourceName=dataSourceName;
    }
    DataSourceName(){

    }
    public String getDataSourceName(){
        return this.dataSourceName;
    }
}

  2、配置类DynamicDataSourceConfig:

  通过@ConfigurationProperties读取配置文件中的数据源配置信息,并通过DruidDataSourceBuilder.create().build()创建数据连接,将多个数据源放入map,注入到IoC中:

**

package com.example.demo.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.example.demo.bean.DynamicDataSource;
import com.example.demo.enums.DataSourceName;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 我命倾尘
 */
@Configuration
public class DynamicDataSourceConfig {
    /**
     * 创建DataSource Bean,将数据源配置从配置文件中读出
     */

    @Bean
    @ConfigurationProperties("spring.datasource.druid.primary")
    public DataSource oneDataSource(){
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.second")
    public DataSource twoDataSource(){
        return DruidDataSourceBuilder.create().build();
    }

    /**
     * 将数据源放入到 这个map中,注入到IoC
     */
    @Bean
    @Primary
    public DynamicDataSource dataSource(DataSource oneDataSource, DataSource twoDataSource){
        Map<Object,Object> targetDataSources=new HashMap<>(2);
        targetDataSources.put(DataSourceName.PRIMARY.getDataSourceName(),oneDataSource);
        targetDataSources.put(DataSourceName.SECOND.getDataSourceName(),twoDataSource);
        return new DynamicDataSource(oneDataSource,targetDataSources);
    }
}

  3、动态数据源DynamicDataSource:

  通过继承AbstractRoutingDataSource类,在构造函数中调用父类的方法,将配置类中放入map的数据源集合定为备选数据源,将传来的oneDataSource作为默认数据源

**

package com.example.demo.bean;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.util.Map;

/**
 * @author 我命倾尘
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    private static final ThreadLocal<String> contextHolder=new ThreadLocal<>();
    /**
     * 配置DataSource
     * 设置defaultTargetDataSource为主数据库
     */
    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object,Object> targetDataSources){
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }
    public static String getDataSource(){
        return contextHolder.get();
    }
    public static void setDataSource(String dataSource){
        contextHolder.set(dataSource);
    }
    public static void clearDataSource(){
        contextHolder.remove();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return getDataSource();
    }
}

  setTargetDataSources设置备选的数据源集合,

  setDefaultTargetDataSource设置默认数据源,

  determineCurrentLookupKey决定当前数据源的对应的key。