SpringBoot多数据源改造(一)
今天做一个需求,业务项目需要访问另一个项目的数据库。
常用两种方案:
1、另一个项目提供一个RestFul API,供调用方通过feign或其它httpClient等方式来访问。
2、项目中通过配置多数据源访问另一个项目库,当然必须有访问权限。
经过对比分析,决定采用第二种方案,原因:一方面,有访问另一个数据源的权限。另一方面,减少一层中间API服务可用性的依赖。
于是开始动手:
第一步,增加新数据源的配置类
@Configuration
@MapperScan(basePackages = {"com.XXX.ecc.YYY.dao"}, sqlSessionTemplateRef = "sqlSessionTemplate2")
public class DataSource2Config {
/**
* 创建datasource对象
* @return
*/
@Bean(name = "dataSource2")
@ConfigurationProperties(prefix = "YYY.datasource.prefix")// prefix值必须是application.properteis中对应属性的前缀
public DataSource dataSource2() {
return DataSourceBuilder.create().build();
}
/**
* 创建sql工程
* @param dataSource
* @return
* @throws Exception
*/
@Bean(name = "sqlSessionFactory2")
public SqlSessionFactory sqlSessionFactory2(@Qualifier("dataSource2") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
//对应mybatis.type-aliases-package配置
bean.setTypeAliasesPackage("com.XXX.ecc.cloudbiz.domain");
//对应mybatis.mapper-locations配置
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:YYY_sqlmap/**/*.xml"));
//开启驼峰映射
bean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
return bean.getObject();
}
/**
* 配置事务管理
* @param dataSource
* @return
*/
@Bean(name = "transactionManager2")
public DataSourceTransactionManager transactionManager2(@Qualifier("dataSource2") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* sqlSession模版,用于配置自动扫描pojo实体类
* @param sqlSessionFactory
* @return
* @throws Exception
*/
@Bean(name = "sqlSessionTemplate2")
public SqlSessionTemplate sqlSessionTemplate2(@Qualifier("sqlSessionFactory2") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
第二步:
在resources下增加YYY_sqlmap文件夹,并且创建YYYMapper.xml,在@MapperScan(basePackages = {"com.XXX.ecc.YYY.dao"}指定的包下,创建YYYMapper.java文件。
第三步:改造原有数据源:增加MapperScan注解,增加事务配置及sessionFactory方法,并在事务、datasource、sessionfactory的方法加上@Primary注解,做为主数据源
@Configuration
@MapperScan(basePackages = {"com.XXX.ecc.zzz.dao"}, sqlSessionTemplateRef = "sqlSessionTemplate")
public class DruidConfig {
private Logger logger = LoggerFactory.getLogger(getClass());
@Value("${spring.datasource.url}")
private String dbUrl;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.initialSize}")
private int initialSize;
@Value("${spring.datasource.minIdle}")
private int minIdle;
@Value("${spring.datasource.maxActive}")
private int maxActive;
@Value("${spring.datasource.maxWait}")
private int maxWait;
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${spring.datasource.validationQuery}")
private String validationQuery;
@Value("${spring.datasource.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.testOnReturn}")
private boolean testOnReturn;
@Value("${spring.datasource.poolPreparedStatements}")
private boolean poolPreparedStatements;
@Value("${spring.datasource.filters}")
private String filters;
@Value("${spring.datasource.loginUserName}")
private String loginUserName;
@Value("${spring.datasource.loginUserPassword}")
private String loginUserPassword;
@Value("${spring.datasource.pwdDecrypt:config.decrypt=true}")
private Properties pwdDecryptProperties;
@Value("${spring.datasource.publicKey:''}")
private String publicKey;
@Value("${spring.datasource.allow}")
private String allowIp;
@Value("${spring.datasource.deny}")
private String denyIp;
@Bean
public ServletRegistrationBean druidServlet() {
ServletRegistrationBean reg = new ServletRegistrationBean();
reg.setServlet(new StatViewServlet());
reg.addUrlMappings("/druid/*");
//IP白名单
reg.addInitParameter("allow",allowIp);
//IP黑名单
reg.addInitParameter("deny",denyIp);
//控制台管理用户
reg.addInitParameter("loginUsername", loginUserName);
reg.addInitParameter("loginPassword", loginUserPassword);
return reg;
}
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
filterRegistrationBean.addInitParameter("profileEnable", "true");
filterRegistrationBean.addInitParameter("principalCookieName", "USER_COOKIE");
filterRegistrationBean.addInitParameter("principalSessionName", "USER_SESSION");
return filterRegistrationBean;
}
@Bean(name = "dataSource")
@Primary