阐明

在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/postgreslocalUserName=postgreslocalingPwd=123456#-----------dci组件数据库信息----------dciDburl=jdbc:postgresql://10.196.1.64:7017/dci_dcidbdciUserName=dci_dcidb_userdciPwd=ULCwLO9p

2.2 其余配置

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

#------是否开启mybatis-plus的分页插件-------------------starfish.data.jdbc.mybatis-plus.pagination.interceptor=true#mybatis-plus配置mybatis-plus.mapper-locations=classpath*:mapper/*Mapper.xmlmybatis-plus.type-aliases-package=com.aries.jc.dciTest.modules.entitymybatis-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;@Mapperpublic 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;@Mapperpublic 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;@Servicepublic 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数据源获取数据