功能: 前端请求接口时携带用户信息,后端拦截器获取用户信息后切换数据源查询数据。
使用场景:多租户,sass,pass等项目。
实现原理:主要通过SpringBoot提供的AbstractRoutingDataSource类,该类允许我们存入一个map,然后在通过数据源获取数据前允许我们指定一个key,然后自动的根据key从map内取对应的数据源。
1 创建 DataSourceHolder类管理数据源的创建和存储@Component
@NoArgsConstructor
@Slf4j
public class DataSourceHolder {
@Autowired
private AbstractRoutingDataSource routingDataSource;
@Resource
private DataSourceInfoMapper dataSourceInfoMapper;
protected final ConcurrentHashMap
2 继承AbstractRoutingDataSource实现动态数据源
@NoArgsConstructor
public class DynamicDataSource extends AbstractRoutingDataSource {
@Resource
private DataSourceHolder dataSourceHolder;
@Override
protected Object determineCurrentLookupKey() {
return dataSourceHolder.getDataSourceKey();
}
}
3 配置数据源
@Configuration
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class DynamicDataSourceConfiguration {
@Autowired
private DataSourceHolder dataSourceHolder;
@Bean("defaultDataSource")
public DataSource defaultDataSource(DataSourceProperties dataSourceProperties){
//创建数据源
return DataSourceBuilder.create()
.driverClassName(dataSourceProperties.getDriverClassName())
.username(dataSourceProperties.getUsername())
.password(dataSourceProperties.getPassword())
.url(dataSourceProperties.getUrl())
.type(dataSourceProperties.getType())
.build();
}
@Primary
@Bean("dataSource")
public DynamicDataSource dynamicDataSource(){
DynamicDataSource dynamicDataSource = new DynamicDataSource();
// 设置默认的数据源
dynamicDataSource.setDefaultTargetDataSource( SpringUtil.getBean("defaultDataSource") );
//设置数据源map
dynamicDataSource.setTargetDataSources( dataSourceHolder.dataSourceMap );
return dynamicDataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dynamicDataSource());
}
}
4 创建过滤器 根据请求动态切换数据源
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter((servletRequest, servletResponse, filterChain) -> {
//默认使用默认的数据源
DataSourceHolder.useDefaultDataSource();
Object dsKey = servletRequest.getParameter("dsKey");
if( dsKey!=null ){
//如果指定了数据源,使用指定的数据源
DataSourceHolder.setDataSourceKey(dsKey.toString());
}
filterChain.doFilter(servletRequest,servletResponse);
});
bean.setOrder(1);
bean.addUrlPatterns("/*");
return bean;
}
}
代码已经放大Gitee上,代码地址:https://gitee.com/GJW520/dynamic-datasource.git



