springboot多数据源聚合统计

 public Pager<Map<String,Object>> queryFlow(Map<String, Object> param, Integer page, Integer pageSize){
        String[] sIds = param.get("sId").toString().split(",");
        param.put("sIds", param.get("sId"));
        List<Map<String,Object>> result = new ArrayList<>();
        //单服统计
        for (String sId : sIds){
            param.put("sId", sId);
            try {
                result.addAll(statisticsDao.selectFlow(param)) ;
            }catch (Exception e){
                System.err.println("链接超时区服:-》" + sId);
            }
        }
        //单服统计结果合并
        Map<String, List<Map<String, Object>>> slist = result.stream().collect(Collectors.groupingBy(e -> e.get("Id").toString()));
        List<Map<String, Object>> finalRes = new ArrayList<>();
        slist.forEach((k, slist) -> {
            Map<String,Object> nmap=new HashMap<>();
            IntSummaryStatistics sumc = slist.stream().collect(Collectors.summarizingInt(e->Integer.valueOf(e.get("uNum").toString())));
            nmap.put("Id", slist.get(0).get("Id"));
            nmap.put("uNum", sumc.getSum());//求和
            finalRes.add(nmap);
        });
        //list分页
        int total = finalRes.size();
        Pager<Map<String,Object>> pager = new Pager<>(total,page,pageSize);
        int start = pager.getStart() > total ? total : pager.getStart();
        int end = page*pageSize > total ? total : page*pageSize;
        List<Map<String, Object>> res = finalRes.subList(start, end);
    
        pager.setList(res);
        return pager;
    }
    @ChangeDataSource
    List<Map<String,Object>> selectFlow(Map<String, Object> param);

自定义注解

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ChangeDataSource {
     String value() default "default";
}

数据源配置

@Configuration
@MapperScan(basePackages = "com.**.dao", sqlSessionFactoryRef = "db1SqlSessionFactory")
public class DataSourceCfg {

    @Primary // 表示这个数据源是默认数据源, 这个注解必须要加,因为不加的话spring将分不清楚那个为主数据源(默认数据源)
    @Bean("primaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.db1") //读取application.yml中的配置参数映射成为一个对象
    public DataSource getDb1DataSource() {
        HikariDataSource datasource =  DataSourceBuilder.create().type(HikariDataSource.class).build();
        datasource.setIdleTimeout(30000);
        datasource.setMaximumPoolSize(60);
        datasource.setMinimumIdle(10);
        datasource.setMaxLifetime(120000);

        //设置默认的数据源
        DataSourceCache.put("default", datasource);
        ThreadLocalDataSource.setLocalSource("default");
        return datasource;
    }

    /**
     * 动态装配所有的数据源
     * @param primaryDataSource
     * @return
     */
    @Bean("dynamicDataSource")
    public DynamicChangeDataSourceConfig setDynamicDataSource(@Qualifier("primaryDataSource") DataSource primaryDataSource){

        //定义实现了AbstractDataSource的自定义aop切换类
        DynamicChangeDataSourceConfig dynamicChangeDataSourceConfig = new DynamicChangeDataSourceConfig();

        //设置默认的数据源
        dynamicChangeDataSourceConfig.setDefaultTargetDataSource(primaryDataSource);
        dynamicChangeDataSourceConfig.setTargetDataSources(DataSourceCache);

        return dynamicChangeDataSourceConfig;
    }


    @Primary
    @Bean("db1SqlSessionFactory")
    public SqlSessionFactory db1SqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        // mapper的xml形式文件位置必须要配置,不然将报错:no statement (这种错误也可能是mapper的xml中,namespace与项目的路径不一致导致)
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
        return bean.getObject();
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dynamicDataSource) {
        return new DataSourceTransactionManager(dynamicDataSource);
    }
}

public class DynamicChangeDataSourceConfig extends AbstractRoutingDataSource{
  
    /**
     * 定义缓存数据源的变量
     */
    public static final Map<Object, Object> DataSourceCache = new ConcurrentHashMap<Object, Object>();
    
    @Override
    protected Object determineCurrentLookupKey() {
        super.afterPropertiesSet();
        return ThreadLocalDataSource.getLocalSource();
    }
}

public class ThreadLocalDataSource {

    private static final ThreadLocal<String> TYPE = new ThreadLocal<>();

    /**
     * 修改当前线程内的数据源id
     * @param key
     */
    public static void setLocalSource(String key){
        TYPE.set(key);
    }

    /**
     * 获取当前线程内的数据源类型
     * @return
     */
    public static String getLocalSource(){
        return TYPE.get();
    }

    /**
     * 清空ThreadLocal中的TYPE
     */
    public static void clear(){
        TYPE.remove();
    }

}

注解切换数据源

@Component
@Aspect
@Order(-1 )
public class DataSourceAspect {

    @Autowired
    private TblGameServerService tblGameServerService;

    @Pointcut("@annotation(com.a.DataSourceConfig.ChangeDataSource)")
    public void pointCut(){}

    @Before(value = "pointCut() && @annotation(changeDataSource)")
    public void operateLog(JoinPoint joinPoint, ChangeDataSource changeDataSource){
   
        Object[] args = joinPoint.getArgs();
        JSONObject obj = JSONObject.fromObject(args[0]);
        String DsKey = obj.get("sId") == null ? null : obj.getString("sId");
        if (DsKey == null){
           //未传入服务器id参数使用默认数据源
           DsKey = changeDataSource.value();
        }
        try {
            initDataSource(DsKey);
        } catch (IOException e) {
           e.printStackTrace();
        }
        ThreadLocalDataSource.setLocalSource(DsKey);
    }

    /**
     * 在切入service方法之后执行
     * 设置回默认数据源
     */
    @After("pointCut()")
    public void afterAspect(){
        System.err.println("切入方法后,开始切换默认数据源");
        ThreadLocalDataSource.clear();
    }

    /**
     * 初始化DataSource
     * 当缓存中没有对应的数据源时,需要去默认数据源查询数据库
     *
     * @param key
     * @return
     */
    public DataSource initDataSource(String key) throws IOException {
        if (DataSourceCache.get(key) != null){ //当前切换数据源是否已缓存,
            return (DataSource)DataSourceCache.get(key);
        }
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setMaxLifetime(15000);
        dataSource.setMaximumPoolSize(9);
        dataSource.setConnectionTimeout(10000);
        dataSource.setIdleTimeout(15000);
        
            //到默认数据库查询服务器信息
            ThreadLocalDataSource.setLocalSource("default");
            TblServer sDb = tblServerService.queryServerBySId(key);
            dataSource.setJdbcUrl(sDb.getDbUrl());
            dataSource.setUsername(sDb.getDbUsername());
            dataSource.setPassword(sDb.getDbPassword());
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
           
        
        DataSourceCache.put(key, dataSource);
        return dataSource;
    }




}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值