summary
If you want to implement a multi-tenant platform in your spare time, you need to implement data separation, dynamic configuration to generate data sources, and build a simple solution based on your own feelings.
dynamic-datasource-spring-boot-starter is a tool used to implement dynamic data source switching in Spring Boot projects. This tool mainly uses this tool to create databases and generate database connections during system operation.
Overall architecture concept
[Create a data source] Use the createDataSource method under the DefaultDataSourceCreator class to create a data source.
[Storage Data Source] Use the addDataSource method of the DynamicRoutingDataSource method to store the data source in key-value pairs.
[Switch data source] Use the **@DS** annotation to dynamically switch the data source.
Operation steps
Create a data source
The method of creating a data source is roughly as follows, mainly to create the parameter configuration of the database, so that the generator can generate a data source.
//By default, use Mysql8.0 and connect to the mysql database table to create new database data through this connection DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource; // Data source parameter configuration DataSourceProperty dataSourceProperty = new DataSourceProperty(); //Fixed use of mysql8 String dbClassType = ""; String dbUrl = ("jdbc:mysql://%s:%s/%s?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8", dbIp, dbPort, dbName); // Use IP to distinguish (dbIp); (userName); (passWord); (dbUrl); (dbClassType); // All data sources are lazy to load, avoid declaring too many connections at once (true); // Generate data source DataSource dataSource = (dataSourceProperty); //Finally store it in ds, and you can use a different key to connect to different data sources later. (dbIp,dataSource);
Later, when calling different databases, you only need to use the **@DS** annotation, the code is as follows:
/** * Call different data connections to generate a new database * @param onlySignIp * @param dbName * @return */ @DS(value = "#onlySignIp") public int createDataSource(String onlySignIp,@Param("dbName")String dbName);
Switch data source
At first I thought that this would allow you to create a database directly in the system. The underlying dynamic-datasource will generate a responsibility chain when initially loading. There are three nodes, namely DsHeaderProcessor, DsSessionProcessor, and DsSpelExpressionProcessor, respectively, corresponding to #header, #session and spel expressions. The source code is as follows:
@Bean @ConditionalOnMissingBean public DsProcessor dsProcessor(BeanFactory beanFactory) { DsHeaderProcessor headerProcessor = new DsHeaderProcessor(); DsSessionProcessor sessionProcessor = new DsSessionProcessor(); DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor(); (new BeanFactoryResolver(beanFactory)); (sessionProcessor); (spelExpressionProcessor); return headerProcessor; }
Here, according to the underlying code, there should be no problem. It seems that the chain of responsibility that is customized with it is not good. Here, I rewrite this chain of responsibility myself (that is, copy the source code myself and inject it into the spring container), and then rewrite it.DsSpelExpressionProcessor,passspelExpression to select the data source.
public class DsSpelExpressionProcessor extends DsProcessor { /** * Parameter discoverer */ private static final ParameterNameDiscoverer NAME_DISCOVERER = new DefaultParameterNameDiscoverer(); /** * Express syntax parser */ private static final ExpressionParser PARSER = new SpelExpressionParser(); /** * Template for parsing context * If the default setting is not set, the way to get the value from the parameter #param1 * Set the value method after the specified template ParserContext.TEMPLATE_EXPRESSION: #{#param1} * issues: /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 = (); StandardEvaluationContext context = new StandardEvaluationContext(arguments); //The first parameter is used by default String replace = ("#", ""); (replace,arguments[0]); final Object value = (key, parserContext).getValue(context); return value == null ? null : (); } public void setParserContext(ParserContext parserContext) { = parserContext; } public void setBeanResolver(BeanResolver beanResolver) { = beanResolver; } }
This allows dynamic switching of data sources to be achieved with @DS annotation.
Follow-up questions
When it is necessary to switch the data source, pass the corresponding data source key information as the first parameter of the Mapper
For example:
/** * Call different data connections to generate a new database * @param onlySignIp * @param dbName * @return */ @DS(value = "#onlySignIp") public int createDataSource(String onlySignIp,@Param("dbName")String dbName);
When switching data sources, the **@DS** annotation must be added, and the key of the corresponding data source must be passed in as the first parameter.
summary
Through the analysis of dynamic-datasource-spring-boot-starter, we simply implement the operation of customizing the creation of data sources and switching the data sources
This is the article about SpringBoot using dynamic-datasource-spring-boot-starter to solve multi-data source problems. For more related SpringBoot multi-data source content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!