SpringBoot设置动态数据源(可在运行时添加)

手机软件开发 2024-9-29 23:28:41 84 0 来自 中国
一、动态多数据源的设置

1.1 创建动态数据源

通过实现Spring提供的AbstractRoutingDataSource类,我们可以实现本身的数据源选择逻辑,从而可以实现数据源的动态切换。
public class DynamicDataSource extends AbstractRoutingDataSource {    @Value("${spring.datasource.default-db-key}")    private String defaultDbKey;·    @Override    protected Object determineCurrentLookupKey() {        String currentDb = DynamicDataSourceService.currentDb();        if (currentDb == null) {            return defaultDbKey;        }        return currentDb;    }}1.2 创建动态数据源设置类

跟设置静态多数据源一样,须要手动设置下面的三个 Bean,只不外DynamicDataSource类的targetDataSources是空的。
@Configurationpublic class DynamicDataSourceConfig {    /**     * 动态数据源     */    @Bean    public DynamicDataSource dynamicDataSource() {        DynamicDataSource dataSource = new DynamicDataSource();        Map<Object, Object> targetDataSources = new HashMap<>();        dataSource.setTargetDataSources(targetDataSources);        return dataSource;    }    /**     * 会话工厂     */    @Bean    public SqlSessionFactoryBean sqlSessionFactoryBean() throws IOException {        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();        configuration.setMapUnderscoreToCamelCase(true);        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();        sqlSessionFactoryBean.setDataSource(dynamicDataSource());        sqlSessionFactoryBean.setConfiguration(configuration);        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:/repository/*.xml"));        return sqlSessionFactoryBean;    }    /**     * 变乱管理器     */    @Bean    public PlatformTransactionManager transactionManager() {        return new DataSourceTransactionManager(dynamicDataSource());    }}1.3 创建动态数据源服务类

这是一个比力焦点的工具类,提供了一些静态方法从而可以实现一些功能,包罗:
动态添加数据源、切换数据源、重置数据源、获取数据源。
在我们 3.1 中创建的 DynamicDataSource 类中,我们就是调用了 DynamicDataSourceService 类的 switchDb
方法实现的数据源选择。
通过查察下面的代码就能看出来利用线程当地的技能实现的多个哀求数据源互不干系。
public class DynamicDataSourceService {    private static final Logger log = LoggerFactory.getLogger(DynamicDataSourceService.class);    private static final Map<Object, Object> dataSources = new HashMap<>();    private static final ThreadLocal<String> dbKeys = ThreadLocal.withInitial(() -> null);    /**     * 动态添加一个数据源     *     * @param name       数据源的key     * @param dataSource 数据源对象     */    public static void addDataSource(String name, DataSource dataSource) {        DynamicDataSource dynamicDataSource = App.context.getBean(DynamicDataSource.class);        dataSources.put(name, dataSource);        dynamicDataSource.setTargetDataSources(dataSources);        dynamicDataSource.afterPropertiesSet();        log.info("添加了数据源:{}",name);    }    /**     * 切换数据源     */    public static void switchDb(String dbKey) {        dbKeys.set(dbKey);    }    /**     * 重置数据源     */    public static void resetDb() {        dbKeys.remove();    }    /**     * 获取当前数据源     */    public static String currentDb() {        return dbKeys.get();    }}至此,动态多数据源的设置就完成了,我们只须要编写数据源天生的逻辑,在步伐运行时调用 addDataSource 方法即可将数据源动态添加到上下文中,并支持动态切换。
下面简单先容一下基于设置文件的数据源天生。
二、数据源天生器

2.1自定义了一个数据源天生器接口用于定义动态天生数据源的要求。

public interface DataSourceProvider {    List<DataSource> provide();}2.2然后编写了一个根据设置文件提供数据源并设置的实现类。

@Component@ConfigurationProperties(prefix = "spring.datasource.hikari")public class YmlDataSourceProvider implements DataSourceProvider {    private List<Map<String, DataSourceProperties>> dataSources;    private DataSource buildDataSource(DataSourceProperties prop) {        DataSourceBuilder<?> builder = DataSourceBuilder.create();        builder.driverClassName(prop.getDriverClassName());        builder.username(prop.getUsername());        builder.password(prop.getPassword());        builder.url(prop.getJdbcUrl());        return builder.build();    }    @Override    public List<DataSource> provide() {        List<DataSource> res = new ArrayList<>();        dataSources.forEach(map -> {            Set<String> keys = map.keySet();            keys.forEach(key -> {                DataSourceProperties properties = map.get(key);                DataSource dataSource = buildDataSource(properties);                DynamicDataSourceService.addDataSource(key, dataSource);            });        });        return res;    }    @PostConstruct    public void init() {        provide();    }    public List<Map<String, DataSourceProperties>> getDataSources() {        return dataSources;    }    public void setDataSources(List<Map<String, DataSourceProperties>> dataSources) {        this.dataSources = dataSources;    }}看一下对应的设置文件内容:
spring:  datasource:    default-db-key: db0    hikari:      data-sources:        - db0:            jdbc-url: jdbc:mysql://127.0.0.1:3306/test            username: root            password: 123456            driver-class-name: com.mysql.cj.jdbc.Driver        - db1:            jdbc-url: jdbc:mysql://127.0.0.1:3306/test2            username: root            password: 123456            driver-class-name: com.mysql.cj.jdbc.Driver如许就实现了应用启动时自动将设置文件中的数据源设置读取并天生数据源注册到上下文中。
当然也可以有其他的实现,好比从数据库读取并设置,或者通过接口哀求的方式天生都可以,只要实现本身的DataSourceProvider就可以了。
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 16:50, Processed in 0.141716 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表