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(), ","));
}
}
若依 多数据源 shardingjdbc配置
最新推荐文章于 2024-04-04 11:07:45 发布