【springboot】动态数据库配置
默认配置
在Spring Boot应用程序中,如果在类路径下存在某个数据库依赖(例如MySQL),则必须提供相应的数据源信息,否则应用程序将无法启动。
- 如果想要在不配置数据源的情况下启动应用程序,可以参照下面的做法修改主类配置
//告诉Spring Boot在启动应用程序时,不自动配置数据源。
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
public class MyApplication{
public static void main(String[] args){
SpringApplication.run(MyApplication.class,args);
}
}
动态数据源切换方法
- 在启动程序中,添加上述exclude配置,使程序在没有配置数据源的时候也能启动
- 当系统初始化后,会向类路径下写入install.back文件
- 创建一个InstallUtils工具类并提供一个返回类型为布尔值isInstall()方法,该方法用于判断install.back文件是否存在
public class InstallUtils {
public static Boolean isInstall() {
String installFile = InstallUtils.class.getResource("/").getPath()+"/install.back";
File file = new File(installFile);
return file.exists();
}
}
- 使用@ConfigurationProperties注解和@Value注解将.properties或.yml配置文件中的属性绑定到Java对象
使用java bean 注入yaml中的配置
@Configuration
public class DruidProperty {
@Value( "${spring.datasource.druid.initialSize}" )
private int initialSize;
@Value ( "${spring.datasource.druid.minIdle}" )
private int minIdle;
@Value ( "${spring.datasource.druid.maxActive}" )
private int maxActive;
@Value("${spring.datasource.druid.maxWait}")
private int maxWait;
@Value ( "${spring.datasource.druid.timeBetweenEvictionRunsMillis}" )
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}")
private int maxEvictableIdleTimeMillis;
@Value("${spring.datasource.druid.validationQuery}")
private String validationQuery;
@Value("${spring.datasource.druid.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.druid.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.druid.testOnReturn}")
private boolean testOnReturn;
public DruidDataSource druidDataSource(DruidDataSource dataSource){
dataSource.setInitialSize(initialSize);
dataSource.setMaxActive(maxActive);
dataSource.setMinIdle(minIdle);
dataSource.setMaxWait(maxWait);
dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
dataSource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
dataSource.setValidationQuery(validationQuery);
dataSource.setTestWhileIdle(testWhileIdle);
dataSource.setTestOnBorrow(testOnBorrow);
dataSource.setTestOnReturn(testOnReturn);
try {
dataSource.addFilters("stat,wall");
} catch (SQLException e) {
e.printStackTrace();
}
return dataSource;
}
}
- 想要实现动态数据源,只需要自定义一个数据源类并继承AbstractRoutingDataSource,然后覆盖determineCurrentLookupKey()即可
public class DynamicDataSource extends AbstractRoutingDataSource {
//构造函数,用于设置默认的数据源和目标数据源
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object,Object>targetDataSource){
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSource);
super.afterPropertiesSet();
}
//覆盖determineCurrentLookupKey()
@Override
protected Object determineCurrentLookupKey() {
return DataSourceHolder.getDatasource();
}
6.注入自定义数据源
- H2数据源是应用的默认数据源,在管理员第一次访问后台或未初始化系统前,都将使用此数据源
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid.h2")
//前缀为“spring.datasource.druid.h2”的配置属性绑定到DruidDataSource的成员变量上。
public DataSource h2DataSource(DruidProperty druidProperty){ //DruidProperty类已经使用@Value注解对其成员变量进行绑定,在此可以直接使用
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
return druidProperty.druidDataSource(dataSource);
}
- 当管理员初始化后台数据后才配置此数据源
- 要实现这样的一种设置,可以借助SpringBoot的@ConditionalOnResource注解来实现。
@ConditionalOnResource注解的原理是当存在某个资源文件时才注册当前的Bean到SpringBoot中
此外,还需要将从前端获取到的数据库连接,用户名和密码手动设置到DruidDataSource上(前端提交的数据库信息被存放到mysql.properties文件中)
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid.mysql")
@ConditionalOnResource(resources = "classpath:install.back")
public DataSource mysqlDataSource(DruidProperty druidProperty){
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
Properties properties = PropertiesUtils.getProperties("mysql.properties");
dataSource.setUrl(properties.getProperty("url"));
dataSource.setUsername(properties.getProperty("username"));
dataSource.setPassword(properties.getProperty("password"));
return druidProperty.druidDataSource(dataSource);
}
- 配置动态数据源
新建一个自定义数据源,使用@Primary注解指定该数据源是主数据源,H2数据源和MySQL数据源的切换将由此数据源完成
@Bean(name = "dynamicDataSource")
@Primary
public DynamicDataSource dynamicDataSource(DataSource h2DataSource,DataSource mysqlDataSource){
Map<Object,Object> targetDataSource = new HashMap<>(2);
targetDataSource.put(DataBaseType.H2.name(),h2DataSource);
targetDataSource.put(DataBaseType.MYSQL.name(),mysqlDataSource);
if(InstallUtils.isInstall()){
return new DynamicDataSource(mysqlDataSource,targetDataSource);
}else{
return new DynamicDataSource(h2DataSource,targetDataSource);
}
}
参考链接:https://blog.csdn.net/tianshan2010/article/details/103941369