本文主要是介绍SpringBoot利用dynamic-datasource-spring-boot-starter解决多数据源问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《SpringBoot利用dynamic-datasource-spring-boot-starter解决多数据源问题》dynamic-datasource-spring-boot-starter是一...
概要
自己闲暇时间想实现一个多租户平台,需要实现数据分离,动态配置OavgTMDcFQ生成数据源,凭着自己的感觉搭建了一套简单的方案
dynamic-datasource-spring-boot-starter 是一个用于在 Spring Boot 项目中实现动态数据源切换的工具,这里主要通过这个工具实现在系统运行中创建数据库,生成数据库连接。
整体架构构想
【创建数据源】使用DefaultDataSourceCreator类下的createDataSource方法创建数据源。
【存储数据源】使用DynamicRoutingDataSource方法的addDataSource方法以键值对存储数据源。
【切换数据源】使用**@DS**注解动态切换数据源。
操作步骤
创建数据源
创建数据源方法大致如下,主要就是创建数据js库的参数配置,让生成器生成数据源。
//默认使用mysql8.0,并且连接mysql数据库表,通过这个连接创建新的数据库数据 DynamicRoutingDataSourpythonce ds = (DynamicRoutingDataSource) dataSource; // 数据源参数配置 DataSou编程rceProperty dataSourceProperty = new DataSourceProperty(); //固定使用mysql8 String dbClassType = "com.mysql.cj.jdbc.Driver"; String dbUrl = String.format("jdbc:mysql://%s:%s/%s?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8", dbIp, dbPort, dbName); /China编程/这里使用IP进行区分 dataSourceProperty.setPoolName(dbIp); dataSourceProperty.setUsername(userName); dataSourceProperty.setPassword(passWord); dataSourceProperty.setUrl(dbUrl); dataSourceProperty.setDriverClassName(dbClassType); // 数据源全部懒加载,避免一次性声明过多连接 dataSourceProperty.setLazy(true); // 生成数据源 DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty); //最后存储到ds中,后面可以用个不同的key去连接不同的数据源 ds.addDataSource(dbIp,dataSource);
后面在调用不同数据库的时候只需要使用**@DS**注解,代码如下:
/** * 调用不同的数据连接生成新的数据库 * @param onlySignIp * @param dbName * @return */ @DS(value = "#onlySignIp") public int createDataSource(String onlySignIp,@Param("dbName")String dbName);
切换数据源
一开始我觉得这样就可以直接在系统中自定义创建数据库,dynamic-datasource底层在初始化加载的时候会生成一条责任链,一共为三个节点分别为DsHeaderProcessor、DsSessionProcessor、DsSpelExpressionProcessor分别对应#header、#session和spel表达式,源码如下:
@Bean @ConditionalOnMissingBean public DsProcessor dsProcessor(BeanFactory beanFactory) { DsHeaderProcessor headerProcessor = new DsHeaderProcessor(); DsSessionProcessor sessionProcessor = new DsSessionProcessor(); DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor(); spelExpressionProcessor.setBeanResolver(new BeanFactoryResolver(beanFactory)); headerProcessor.setNextProcessor(sessionProcessor); sessionProcessor.setNextProcessor(spelExpressionProcessor); return headerProcessor; }
在这里 根据底层代码理论上来说是不会应该有问题的,好像是用它自定义的责任链不行,这里我就自己重写了这条责任链(也就自己复制源代码将他注入到spring容器中),然后在重写DsSpelExpressionProcessor,通过spel表达式来选择数据源。
public class DsSpelExpressionProcessor extends DsProcessor { /** * 参数发现器 */ private static final ParameterNameDiscoverer NAME_DISCOVERER = new DefaultParameterNameDiscoverer(); /** * Express语法解析器 */ private static final ExpressionParser PARSER = new SpelExpressionParser(); /** * 解析上下文的模板 * 对于默认不设置的情况下,从参数中取值的方式 #param1 * 设置指定模板 ParserContext.TEMPLATE_EXPRESSION 后的取值方式: #{#param1} * issues: https://github.com/baomidou/dynamic-datasource-spring-boot-starter/issues/199 */ private ParserContext parserContext = new ParserContext() { @Override public boolean isTemplate() { return false; } @Override public String getExpressionPrefix() { return null; } @Override public String getExpressionSuffix() { return null; } }; private BeanResolver beanResolver; @Override public boolean matches(String key) { return true; } @Override public String doDetermineDatasource(MethodInvocation invocation, String key) { Object[] arguments = invocation.getArguments(); StandardEvaLuationContext context = new StandardEvaluationContext(arguments); //默认使用第一个参数 String replace = key.replace("#", ""); context.setVariable(replace,arguments[0]); final Object value = PARSER.parseExpression(key, parserContext).getValue(context); return value == null ? null : value.toString(); } public void setParserContext(ParserContext parserContext) { this.parserContext = parserContext; } public void setBeanResolver(BeanResolver beanResolver) { this.beanResolver = beanResolver; } }
这样配合@DS注解就可以实现数据源的动态切换了。
后续问题
在需要切换数据源的情况下,将对应数据源Key信息作为Mapper第一个参数传递
例如:
/** * 调用不同的数据连接生成新的数据库 * @param onlySignIp * @param dbName * @return */ @DS(value = "#onlySignIp") public int createDataSource(String onlySignIp,@Param("dbName")String dbName);
在切换数据源的情况下必须要加上**@DS**注解,而且还必须将对应数据源的Key作为第一个参数进行传入
小结
通过对 dynamic-datasource-spring-boot-starter 的剖析,我们简单的实现了自定义创建数据源,切换数据源的操作
到此这篇关于SpringBoot利用dynamic-datasource-spring-boot-starter解决多数据源问题的文章就介绍到这了,更多相关SpringBoot多数据源内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!
这篇关于SpringBoot利用dynamic-datasource-spring-boot-starter解决多数据源问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!