若依 多数据源 shardingjdbc配置

package com.zx.framework.config;

import cn.hutool.core.util.ArrayUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.util.Utils;
import com.zx.common.constant.SystemConstants;
import com.zx.common.enums.DataSourceType;
import com.zx.common.utils.StringUtils;
import com.zx.common.utils.spring.SpringUtils;
import com.zx.framework.config.MybatisInterceptor.CustomUtils.CustomMybayisInterceptorUtils;
import com.zx.framework.config.properties.DruidProperties;
import com.zx.framework.datasource.DynamicDataSource;
import com.zx.framework.shardingConfig.DynamicTablesProperties;
import com.zx.framework.shardingConfig.genTables.GenTableNodes;
import org.apache.shardingsphere.driver.api.ShardingSphereDataSourceFactory;
import org.apache.shardingsphere.infra.config.algorithm.ShardingSphereAlgorithmConfiguration;
import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.strategy.sharding.StandardShardingStrategyConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.servlet.*;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;


/**
 * druid 配置多数据源
 *
 * @author ruoyi
 */
@Configuration
//@EnableConfigurationProperties(DynamicTablesProperties.class)
public class DruidConfig
{
    private static Logger log= LoggerFactory.getLogger(DruidConfig.class);

    @Autowired
    private DynamicTablesProperties dynamicTables;

    @Bean
    @ConfigurationProperties("spring.datasource.druid.master")
    public DataSource masterDataSource(DruidProperties druidProperties)
    {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }
    @Bean(name = "shardingDataSource")
    @ConditionalOnProperty(name = "enable", prefix="sharding.tables" ,havingValue="true")
    public DataSource shardingDataSource(@Qualifier("masterDataSource") DataSource masterDataSource) throws SQLException {
        //https://www.65580.net/205031.html
        //https://shardingsphere.apache.org/document/5.1.2/cn/shardingsphere_docs_cn.pdf
        //https://shardingsphere.apache.org/document/5.1.2/cn/dev-manual/sharding/
        if(!dynamicTables.isEnable()){
            log.warn("sharding.table close");
            return null;
        }
        Map<String, DataSource> dataSourceMap = new HashMap<>();
        dataSourceMap.put(DataSourceType.SHARDING.name(),masterDataSource);
        DataSource shardingDataSource = ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(createShardingRuleConfiguration(masterDataSource)),getProperties());
        // 获取数据源对象
        return shardingDataSource;
    }


    @Bean
    @ConfigurationProperties("spring.datasource.druid.slave")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
    public DataSource slaveDataSource(DruidProperties druidProperties)
    {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }
    @Primary
    @Bean(name = "dynamicDataSource")
    @ConditionalOnBean(name="shardingDataSource")
    public DynamicDataSource dataSource_s(@Qualifier("shardingDataSource")DataSource shardingDataSource)
    {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.SHARDING.name(), shardingDataSource);
        setDataSource(targetDataSources,DataSourceType.MASTER.name() , "masterDataSource");
        setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
        log.info("use >> "+DataSourceType.SHARDING.name()+" datasource");
        return new DynamicDataSource(shardingDataSource, targetDataSources);
    }
    @Primary
    @Bean(name = "dynamicDataSource")
    @ConditionalOnMissingBean(name="shardingDataSource")
    public DynamicDataSource dataSource_m(@Qualifier("masterDataSource") DataSource masterDataSource)
    {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
        setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
        log.info("use >> "+DataSourceType.MASTER.name()+" datasource");
        return new DynamicDataSource(masterDataSource, targetDataSources);

    }
    /**
     * 设置数据源
     * 
     * @param targetDataSources 备选数据源集合
     * @param sourceName 数据源名称
     * @param beanName bean名称
     */
    public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
    {
        try
        {
            DataSource dataSource = SpringUtils.getBean(beanName);
            targetDataSources.put(sourceName, dataSource);
        }
        catch (Exception e)
        {
        }
    }

    /**
     * 去除监控页面底部的广告
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Bean
    @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
    {
        // 获取web监控页面的参数
        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
        // 提取common.js的配置路径
        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
        final String filePath = "support/http/resources/js/common.js";
        // 创建filter进行过滤
        Filter filter = new Filter()
        {
            @Override
            public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
            {
            }

            @Override
            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                    throws IOException, ServletException
            {
                chain.doFilter(request, response);
                // 重置缓冲区,响应头不会被重置
                response.resetBuffer();
                // 获取common.js
                String text = Utils.readFromResource(filePath);
                // 正则替换banner, 除去底部的广告信息
                text = text.replaceAll("<a.*?banner\"></a><br/>", "");
                text = text.replaceAll("powered.*?shrek.wang</a>", "");
                response.getWriter().write(text);
            }

            @Override
            public void destroy()
            {
            }
        };
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(filter);
        registrationBean.addUrlPatterns(commonJsPattern);
        return registrationBean;
    }
    /**
     * 系统参数配置
     */
    private Properties getProperties()
    {
        Properties shardingProperties = new Properties();
        shardingProperties.put("sql.show", true);
        shardingProperties.put("sql-show", true);
        return shardingProperties;
    }

    /**
     * 生成规则
     * @param masterDataSource
     * @return
     * @throws SQLException
     */
    private ShardingRuleConfiguration createShardingRuleConfiguration(DataSource masterDataSource ) throws SQLException {
        if(!dynamicTables.isEnable()){
            log.warn("sharding.table close");
            return null;
        }
        if (dynamicTables.getColumn() == null|| StringUtils.isEmpty(dynamicTables.getColumn())) {
            log.warn("sharding.table.column 为空");
            return null;
        }
        List<String> tables = CustomMybayisInterceptorUtils.getTableNameByCon(masterDataSource.getConnection(), dynamicTables);
        if (tables == null||tables.size()==0) {
            log.warn("sharding.tables 为空");
            return null;
        }
        Set<Long> orgIdSet = new HashSet<>();
        orgIdSet.add(SystemConstants.ADMIN_ORG_ID);
        if(ArrayUtil.isNotEmpty(dynamicTables.getViews())){
            tables.addAll(Arrays.asList(dynamicTables.getViews()));
        }
        /* 分片规则配置 */
        // 表达式 ds_${0..1} 枚举值表示的是主从配置的逻辑数据源名称列表
        /*ShardingTableRuleConfiguration tOrderRuleConfiguration = new ShardingTableRuleConfiguration("t_order", "ds_${0..1}.t_order_${[0, 1]}");
        tOrderRuleConfiguration.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("order_id", "snowflake"));
        tOrderRuleConfiguration.setTableShardingStrategy(new   StandardShardingStrategyConfiguration("order_id", "tOrderInlineShardingAlgorithm"));
        Properties tOrderShardingInlineProps = new Properties();
        tOrderShardingInlineProps.setProperty("algorithm-expression", "t_order_${order_id %2}");
        tOrderRuleConfiguration.getShardingAlgorithms().putIfAbsent( "tOrderInlineShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("INLINE", tOrderShardingInlineProps));

        ShardingTableRuleConfiguration tOrderItemRuleConfiguration = new ShardingTableRuleConfiguration("t_order_item", "ds_${0..1}.t_order_item_${[0, 1]}");
        tOrderItemRuleConfiguration.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("order_item_id", "snowflake"));
        tOrderRuleConfiguration.setTableShardingStrategy(new StandardShardingStrategyConfiguration("order_item_id", "tOrderItemInlineShardingAlgorithm"));
        Properties tOrderItemShardingInlineProps = new Properties();
        tOrderItemShardingInlineProps.setProperty("algorithm-expression", "t_order_item_${order_item_id % 2}");
        tOrderRuleConfiguration.getShardingAlgorithms().putIfAbsent("tOrderItemInlineShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("INLINE",tOrderItemShardingInlineProps));

        ShardingRuleConfiguration shardingRuleConfiguration = new ShardingRuleConfiguration();
        shardingRuleConfiguration.getTables().add(tOrderRuleConfiguration);
        shardingRuleConfiguration.getTables().add(tOrderItemRuleConfiguration);
        shardingRuleConfiguration.getBindingTableGroups().add("t_order, t_order_item");
        shardingRuleConfiguration.getBroadcastTables().add("t_bank");*/

        ShardingRuleConfiguration result = new ShardingRuleConfiguration();
        //添加所有表以及相关规则
        result.getTables().addAll(getOrderTableRuleConfigurations(tables,orgIdSet));
         //生成规则
        getAlgorithmExpressions(result, tables,orgIdSet);
        return result;
    }
    private Collection<ShardingTableRuleConfiguration> getOrderTableRuleConfigurations( List<String> tables,Set<Long> orgIdSet  ) {
        List<ShardingTableRuleConfiguration> retList=new ArrayList<>(tables.size());
        for(String tableName: tables){
            // 生成datanodes
            String actualDataNodes = GenTableNodes.buildNodes(tableName, orgIdSet, DataSourceType.SHARDING.name());
            ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration(tableName, actualDataNodes);
            // 配置分表策略
            if (tableName.startsWith("v_")) {
                //配置分片规则
                result.setTableShardingStrategy(new StandardShardingStrategyConfiguration("view_"+dynamicTables.getColumn(),tableName+"_inline"));
            }else {
                result.setTableShardingStrategy(new StandardShardingStrategyConfiguration(dynamicTables.getColumn(),tableName+"_inline"));
            }
            retList.add(result);
        }
        return retList;
    }
    private void getAlgorithmExpressions(ShardingRuleConfiguration result, List<String> tables,Set<Long> orgIdSet){
        for(String tableName: tables){
            // 生成algorithmExpression
            //String algorithmExpression = GenTableNodes.buildAlgorithmExpression(tableName, orgIdSet);
            Properties props = new Properties();
            props.setProperty("strategy", "STANDARD");
            props.setProperty("algorithmClassName", "com.zx.framework.shardingConfig.PreciseModuloShardingTableAlgorithm");
            result.getShardingAlgorithms().put(tableName+"_inline", new ShardingSphereAlgorithmConfiguration("CLASS_BASED",props));
        }
        //添加绑定表
        result.getBindingTableGroups().add(StringUtils.join(tables.toArray(), ","));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值