赞
踩

DataSource的基本角色是ConnectionFactory,所有的数据库连接将通过DataSource接口统一管理。
DataSource实现类根据功能强弱可以划分为以下三类:

org.springframework.jdbc.datasource.DriverManagerDataSource.
顾名思义,DriverManagerDataSource的提出,主要是为了替换最古老的基于java.sql.DriverManager获取连接的方式。
Class.forName("com.mysql.jdbc.Driver");
DriverManager.getConnection("jdbc:mysql://110.40.155.17:3306/test?userSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8",
"root","126433");


@Configuration @Data @ConfigurationProperties(prefix = "spring.datasource") public class DataSourceConfig { private String url; private String username; private String password; private String driverClassName; @Bean public DriverManagerDataSource driverManagerDataSource(){ DriverManagerDataSource source = new DriverManagerDataSource(); source.setUrl(url); source.setDriverClassName(driverClassName); source.setPassword(password); source.setUsername(username); return source; } }
org.springframework.jdbc.datasource.SingleConnectionDataSource

@Bean
public SingleConnectionDataSource singleConnectionDataSource(){
SingleConnectionDataSource source = new SingleConnectionDataSource();
source.setUrl(url);
source.setDriverClassName(driverClassName);
source.setPassword(password);
source.setUsername(username);
//可以设置是否开启自动提交---默认为true
source.setAutoCommit(true);
//close方法调用,也不会关闭连接
source.setSuppressClose(false);
return source;
}

常见的数据库连接池有cp30,driud等,这需要引入额外的依赖,这里不多进行演示。
对于这类DataSource,还需要额外指定连接池大小等参数。








Spring提供了DelegatingDataSource的几个实现类




所谓主权独立是指系统中的每个数据源都对外独立承担公开数据库资源的职能:


该种数据源在spring中的简单使用如下:
public class Main { public static void main(String[] args) { DataSource mainDataSource = getMainDataSource(); JdbcTemplate main=new JdbcTemplate(mainDataSource); DataSource otherDataSource = getOtherDataSource(); JdbcTemplate other = new JdbcTemplate(otherDataSource); } private static javax.sql.DataSource getMainDataSource() { BasicDataSource basicDataSource = new BasicDataSource(); YamlUtil yamlUtil = new YamlUtil("application.yml"); basicDataSource.setDriverClassName(yamlUtil.get("spring.datasource.driver-class-name")); basicDataSource.setUrl(yamlUtil.get("spring.datasource.url")); basicDataSource.setUsername(yamlUtil.get("spring.datasource.username")); basicDataSource.setPassword(yamlUtil.get("spring.datasource.password")); return basicDataSource; } private static javax.sql.DataSource getOtherDataSource() { //如何获取看具体的业务需求 ... return basicDataSource; } }
只需要不同的JdbcTemplate拥有不同的DataSource即可。


AbstractRoutingDataSource原理:
@Override
public Connection getConnection() throws SQLException {
return determineTargetDataSource().getConnection();
}
protected DataSource determineTargetDataSource() {
Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
//determineCurrentLookupKey抽象方法,负责返回指定的key,然后去集合中动态获取到目标的dataSource
Object lookupKey = determineCurrentLookupKey();
DataSource dataSource = this.resolvedDataSources.get(lookupKey);
if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
dataSource = this.resolvedDefaultDataSource;
}
if (dataSource == null) {
throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
}
return dataSource;
}
@Nullable
private Map<Object, Object> targetDataSources;
这里演示一下使用AbstractRoutingDataSource实现多数据源的管控:
@Data
public class DynamicDataSource extends AbstractRoutingDataSource {
private String datasource;
@Override
protected Object determineCurrentLookupKey() {
return datasource;
}
}
public class DataSourceTestHandler { /** * 获得helper数据库的数据源 */ public static DataSource getHelperDataSource(){ HikariDataSource dataSource = new HikariDataSource(); dataSource.setJdbcUrl("xxx"); dataSource.setUsername("xxx"); dataSource.setPassword("xxx"); return dataSource; } /** * 获得training数据库的数据源 */ public static DataSource getTrainingDataSource(){ HikariDataSource dataSource = new HikariDataSource(); dataSource.setJdbcUrl("xxx"); dataSource.setUsername("xxx"); dataSource.setPassword("xxx"); return dataSource; } public static DataSource getManagerDataSource(){ DynamicDataSource dynamicDataSource = new DynamicDataSource(); Map<Object,Object> sources=new HashMap<>(); sources.put("helper",getHelperDataSource()); sources.put("training",getTrainingDataSource()); dynamicDataSource.setTargetDataSources(sources); return dynamicDataSource; } }
动态切换测试:
/**
* 多数据源结果测试
*/
@ResponseBody
@GetMapping("/{dataSource}/{tableName}")
public AjaxResponse testMultiplyDataSource(@PathVariable(name = "dataSource") String dataSource,
@PathVariable(name = "tableName")String tableName) throws SQLException {
log.info("需要进行测试的数据源为: {}",dataSource);
return testService.testMultiplyDataSource(dataSource,tableName);
}
@Service
public class TestServiceImp implements TestService {
@Override
public AjaxResponse testMultiplyDataSource(String dataSource,String tableName) throws SQLException {
DynamicDataSource managerDataSource = (DynamicDataSource)getManagerDataSource();
managerDataSource.setDatasource(dataSource);
managerDataSource.afterPropertiesSet();
JdbcTemplate jdbcTemplate = new JdbcTemplate(managerDataSource);
List<Map<String, Object>> list = jdbcTemplate.queryForList("select * from " + tableName);
return AjaxResponse.success(list);
}
}



合纵连横和主权独立可以联合使用:

可以用于存在多个数据源的场景,并且每个数据源存在多个实例,需要进行负载均衡

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。