乐趣区

关于java:JC框架DB模块

阐明

在 jc 脚手架下引入 DB 模块,进行多数据源的主动寻址;
上面以 dci 组件数据库和本地数据库为例,展现如何在 jc 脚手架下引入 DB 模块并如何进行配置

引入 DB 模块的必要性

在开发中,常常会须要获取其余组件数据库中的数据,通常有两种方法:
(1)通过 Feign 调用;间接调用相干组件的接口获取数据
但有时候组件的接口没有或者不能调用,这个时候能够采纳第二种办法:
(2)引入 DB 模块,间接连贯组件的数据库,从数据库间接获取数据

1. 相干的 pom 依赖

在 business 文件夹下的 pom 文件中引入以下 pom 依赖:

<!-- 多数据源寻址 pom 依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-core</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-extension</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-extension</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.9</version>
        </dependency>
        <dependency>
            <groupId>com.aries.jc.common</groupId>
            <artifactId>aries-jc-bic-resttemplate</artifactId>
        </dependency>

2. 配置文件

2.1 多数据源的连贯配置

在 dev 配置文件中配置须要的多数据源的连贯信息

#------------ 本组件数据库 --------------
localDburl=jdbc:postgresql://127.0.0.1:5432/postgres
localUserName=postgres
localingPwd=123456
#-----------dci 组件数据库信息 ----------
dciDburl=jdbc:postgresql://10.196.1.64:7017/dci_dcidb
dciUserName=dci_dcidb_user
dciPwd=ULCwLO9p

2.2 其余配置

这些配置不晓得是否有必要配置,但加上没有影响,去掉后不晓得是否会报错

#------ 是否开启 mybatis-plus 的分页插件 -------------------
starfish.data.jdbc.mybatis-plus.pagination.interceptor=true
#mybatis-plus 配置
mybatis-plus.mapper-locations=classpath*:mapper/*Mapper.xml
mybatis-plus.type-aliases-package=com.aries.jc.dciTest.modules.entity
mybatis-plus.configuration.map-underscore-to-camel-case=true
#profile 为 dev 时是否开启 mybatis-plus SQL 执行效率插件
starfish.data.jdbc.mybatis-plus.dev.performancce.interceptor=true

3. 引入 DB 模块

3.1 DataSourceSwitchAspect 文件

本文件中须要更改的是 @Pointcut 注解前面括号中的目录地址
在本文中只有两个数据源须要切换,如果理论开发中有更多的数据源须要切换,则在该文件中依照 db1Aspect()、db2Aspect()办法创立第三个、第四个

package com.aries.jc.dciTest.modules.db;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Order(-1) // 这是为了保障 AOP 在事务注解之前失效,Order 的值越小, 优先级越高
public class DataSourceSwitchAspect {private final static Logger log = LoggerFactory.getLogger(DataSourceSwitchAspect.class);

    // 须要从本地数据库获取的数据,须要在 mapper 文件夹下创立 local 文件夹,并将 mapper 文件定义在 local 文件夹下,括号中的地址依据理论我的项目目录进行更改
    @Pointcut("execution(* com.aries.jc.dciTest.modules.mapper.local..*.*(..))")
    private void db1Aspect() {}

    // 须要从 dci 数据库获取的数据,须要在 mapper 文件夹下创立 dci 文件夹,并将 mapper 文件定义在 dci 文件夹下,括号中的地址依据理论我的项目目录进行更改
    @Pointcut("execution(* com.aries.jc.dciTest.modules.mapper.dci..*.*(..))")
    private void db2Aspect() {}


    @Before("db1Aspect()")
    public void db1() {log.debug("切换到 local 数据源...");
        DbContextHolder.setDbType(DBTypeEnum.db1);
    }

    @Before("db2Aspect()")
    public void db2() {log.debug("切换到 dci 数据源...");
        DbContextHolder.setDbType(DBTypeEnum.db2);
    }
}

3.2 DbConfig 文件

批改 1:@MapperScan 注解前面括号中的目录地址
批改 2:@Value 注解前面括号中的内容,依据配置文件中的配置做出具体批改
本文中只有两个数据源须要切换,如果理论开发中须要更多数据源,则可在本文件中参考 @Bean(name = “db1”)、@Bean(name = “db2”),创立其余数据源的 Bean

package com.aries.jc.dciTest.modules.db;


import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

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

@Configuration
@MapperScan("com.aries.jc.dciTest.**.mapper*")
public class DbConfig {private final static Logger log = LoggerFactory.getLogger(DbConfig.class);

    // 组件示意信息:也是在配置文件中进行配置
    @Value("${base.application.componentId}")
    private String componentId;

    // 配置文件中数据库的信息
    @Value("${localDburl}")
    private String localDburl;
    @Value("${localUserName}")
    private String localUserName;
    @Value("${localingPwd}")
    private String localingPwd;
    @Value("${dciDburl}")
    private String dciDburl;
    @Value("${dciUserName}")
    private String dciUserName;
    @Value("${dciPwd}")
    private String dciPwd;

    private static String driverClass = "org.postgresql.Driver";

    @Bean
    public PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();
    }


    @Bean(name = "db1")
    public DataSource db1() {// SegmentInfo segmentInfo = myHikDiscoveryClient.findAmqServer(componentId,dbSegmentId);
    /*    log.info("初始化新组件数据库 >>>>>>componentId="+componentId+",dbSegmentId="+dbSegmentId+",segmentInfo="+ JSONObject.toJSONString(segmentInfo));
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl("jdbc:postgresql://"+segmentInfo.getIp()+":"+segmentInfo.getPort()+"/"+segmentInfo.getDbName());
        dataSource.setUsername(segmentInfo.getDbusername());
        dataSource.setPassword(segmentInfo.getDbpassword());*/

        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl(localDburl);
        dataSource.setUsername(localUserName);
        dataSource.setPassword(localingPwd);

        return dataSource;


    }

    @Bean(name = "db2")
    public DataSource db2() {DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl(dciDburl);
        dataSource.setUsername(dciUserName);
        dataSource.setPassword(dciPwd);
        return dataSource;
    }

    /**
     * 动静数据源配置
     *
     * @return
     */

    @Bean
    @Primary
    public DataSource multipleDataSource(@Qualifier("db1") DataSource db1,
                                         @Qualifier("db2") DataSource db2
    ) {DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DBTypeEnum.db1.getValue(), db1);
        targetDataSources.put(DBTypeEnum.db2.getValue(), db2);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(db1); // 程序默认数据源,这个要依据程序调用数据源频次,常常把常调用的数据源作为默认
        return dynamicDataSource;
    }

    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() throws Exception {MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(multipleDataSource(db1(), db2()));

        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCacheEnabled(false);
        sqlSessionFactory.setConfiguration(configuration);
        sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*Mapper.xml"));
        //PerformanceInterceptor(),OptimisticLockerInterceptor()
        // 增加分页性能
        sqlSessionFactory.setPlugins(new Interceptor[]{paginationInterceptor()
        });
//        sqlSessionFactory.setGlobalConfig(globalConfiguration()); // 正文掉全局配置,因为在 xml 中读取就是全局配置
        return sqlSessionFactory.getObject();}
}

3.3 DbContextHolder 文件

此文件不须要批改

package com.aries.jc.dciTest.modules.db;

public class DbContextHolder {private static final ThreadLocal contextHolder = new ThreadLocal<>();

    /**
     * 设置数据源
     *
     * @param dbTypeEnum
     */

    public static void setDbType(DBTypeEnum dbTypeEnum) {contextHolder.set(dbTypeEnum.getValue());
    }


    /**
     * 获得以后数据源
     *
     * @return
     */

    public static String getDbType() {return (String) contextHolder.get();}


    /**
     * 革除上下文数据
     */

    public static void clearDbType() {contextHolder.remove();
    }
}

3.4 DBTypeEnum 文件

本文只有两个数据源进行切换,如果波及到 3 个、4 个或者更多,间接在文件中增加
db1(“db1”),
db2(“db2”),
db3(“db3”),
db4(“db4”);

即可

package com.aries.jc.dciTest.modules.db;

public enum DBTypeEnum {db1("db1"),
    db2("db2");
    private String value;

    DBTypeEnum(String value) {this.value = value;}

    public String getValue() {return value;}
}

3.5 DynamicDataSource 文件

此文件不须要批改

package com.aries.jc.dciTest.modules.db;

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

public class DynamicDataSource extends AbstractRoutingDataSource {

    /**
     * 获得以后应用哪个数据源
     *
     * @return
     */
    @Override
    protected Object determineCurrentLookupKey() {return DbContextHolder.getDbType();
    }
}

4. 测试

4.1 创立实体类

在 business 文件夹下创立 entity 文件夹,在 entity 文件夹下创立 dci、local 文件夹
在 dci 文件夹下创立实体类:

package com.aries.jc.dciTest.modules.entity.dci;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.models.auth.In;
import lombok.Data;

import java.sql.Timestamp;

@Data
@TableName("org_info_count")
public class OrgInfoCount {@TableField("org_index_code")
    private String orgIndexCode;

    @TableField("org_index_code_in")
    private String orgIndexCodeIn;

    @TableField("org_index_name")
    private String orgIndexName;

    @TableField("org_index_type")
    private String orgIndexType;

    @TableField("insert_count")
    private Integer insertCount;

    @TableField("not_insert_count")
    private Integer notInsertCount;

    @TableField("total")
    private Integer total;

    @TableField("update_time")
    private Timestamp updateTime;
}

在 local 文件夹下创立实体类:

package com.aries.jc.dciTest.modules.entity.local;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.sql.Timestamp;

@Data
@TableName("tb_point_config")
public class pointConfig {@TableField("point_name")
    @ApiModelProperty("点位类型名称")
    private String pointName;

    @TableField("point_type")
    @ApiModelProperty("点位类型  0- 个别类型 1- 蓝天卫士;2- 重点监控")
    private Integer pointType;

    @TableField("point_icon_url")
    @ApiModelProperty("点位图标 url")
    private String pointIconUrl;

    @TableField("point_icon_name")
    @ApiModelProperty("点位图标名称")
    private String pointIconName;

    @TableField("aggre_icon_url")
    @ApiModelProperty("聚合图标 url")
    private String aggreIconUrl;

    @TableField("aggre_icon_name")
    @ApiModelProperty("聚合图标 name")
    private String aggreIconName;

    @TableField("create_time")
    @ApiModelProperty("创立工夫")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Timestamp createTime;

    @TableField("create_user")
    @ApiModelProperty("创建人名称")
    private String createUser;

    @TableField("update_time")
    @ApiModelProperty("更新工夫")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Timestamp updateTime;

    @TableField("update_user")
    @ApiModelProperty("更新人名称")
    private String updateUser;

    @TableField("delete")
    @ApiModelProperty("是否删除  1- 未删除  -1- 以删除")
    private Integer delete;
}

4.2 创立 Mapper

在 mapper 文件夹下创立 dci、local 文件夹,
在 dci 文件夹下创立 mapper:

package com.aries.jc.dciTest.modules.mapper.dci;

import com.aries.jc.dciTest.modules.entity.dci.OrgInfoCount;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hikvision.ga.common.BaseResult;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface OrgInfoCountMapper extends BaseMapper<OrgInfoCount> {@Select("select * from org_info_count")
    List<OrgInfoCount> getAllOrgInfo();}

在 local 文件夹下创立 mapper:

package com.aries.jc.dciTest.modules.mapper.local;

import com.aries.jc.dciTest.modules.entity.local.PointConfig;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface PointConfigMapper extends BaseMapper<PointConfig> {@Select("select * from tb_point_config")
    List<PointConfig> getAllPoint();}

4.3 创立 service 接口

在 service 层中不须要辨别 dci 数据源和 local 数据源,可间接将两者的接口定义在一个 service 接口文件中

4.4 创立 service 接口实现类

在 service 层接口实现类中不须要辨别 dci 数据源和 local 数据源,可间接将两者的接口定义在一个 service 接口实现类文件中

package com.aries.jc.dciTest.modules.service.impl;

import com.aries.jc.dciTest.modules.entity.dci.OrgInfoCount;
import com.aries.jc.dciTest.modules.entity.local.PointConfig;
import com.aries.jc.dciTest.modules.mapper.dci.OrgInfoCountMapper;
import com.aries.jc.dciTest.modules.mapper.local.PointConfigMapper;
import com.aries.jc.dciTest.modules.rs.DciClientV1;
import com.aries.jc.dciTest.modules.rs.DciClientV2;
import com.aries.jc.dciTest.modules.rs.DciClientV3;
import com.aries.jc.dciTest.modules.service.DciService;
import com.hikvision.ga.common.BaseResult;
import com.hikvision.ga.dci.api.v1.dto.BasePageDto;
import com.hikvision.ga.dci.api.v1.dto.UnitListDto;
import com.hikvision.ga.dci.api.v2.param.ParamUnitList;
import com.hikvision.ga.dci.api.v3.dto.CountReq;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class DciServiceImpl implements DciService {private static final Logger LOGGER = LoggerFactory.getLogger(DciServiceImpl.class);

    @Autowired
    private OrgInfoCountMapper orgInfoCountMapper;
    @Autowired
    private PointConfigMapper pointConfigMapper;

    /**
     * 获取 dci 数据库中 org_info_count 表所有数据,测试多数据源切换
     * @return
     */
    @Override
    public BaseResult<List<OrgInfoCount>> getAllInfo() {BaseResult<List<OrgInfoCount>> baseResult = new BaseResult<>();
        List<OrgInfoCount> list = new ArrayList<>();

        try {list = orgInfoCountMapper.getAllOrgInfo();
            baseResult.setData(list);
            baseResult.setCode("0");
            baseResult.setMsg("获取胜利");
            return baseResult;
        }catch (Exception e){LOGGER.error("获取失败:{}", e);
        }
        baseResult.setCode("-1");
        baseResult.setMsg("获取失败");
        return baseResult;
    }

    /**
     * 获取 local 数据库中 tb_point_config 表所有数据,测试多数据源切换
     * @return
     */
    @Override
    public BaseResult<List<PointConfig>> getAllPoint() {BaseResult<List<PointConfig>> baseResult = new BaseResult<>();
        List<PointConfig> list = new ArrayList<>();

        try {list = pointConfigMapper.getAllPoint();
            baseResult.setData(list);
            baseResult.setCode("0");
            baseResult.setMsg("获取胜利");
            return baseResult;
        }catch (Exception e){LOGGER.error("获取失败:{}", e);
        }
        baseResult.setCode("-1");
        baseResult.setMsg("获取失败");
        return baseResult;
    }


}

4.5 创立 controller 层

controller 层同样不须要辨别不同的数据源,能够定义在同一个 controller 文件中

4.6 swagger 测试

(1)local 数据源获取数据


(2)dci 数据源获取数据

退出移动版