背景:
产品已经上线,目前为了更好的查看线上数据,所以计划开发一套boss运营系统,供内部人员使用,boss系统需要建自己的一套数据表数据结构,初期本来想跟业务表放在一起,但是思前想后,Boss系统表结构和业务数据放在一个数据库不是很合理,所以前期采用动态数据源选择来加载或者操作合法数据。
实现过程:
1.编写application.yml --> mybatisplus配置,mysql多数据源配置。
spring:
application:
name: @spring.application.name@
environment: @spring.application.environment@
datasource.druid:
#数据源1
datasource1:
url: jdbc:mysql:///mds
username: root
password: 123456
filters: config
db-type: mysql
driver-class-name: com.mysql.jdbc.Driver
initial-size: 1
min-idle: 1
max-active: 20
max-wait: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
filter:
stat:
enabled: false
wall:
enabled: true
web-stat-filter:
enabled: false
stat-view-servlet:
enabled: false
#数据源1
datasource1:
url: jdbc:mysql:///mds
username: root
password: 123456
filters: config
db-type: mysql
driver-class-name: com.mysql.jdbc.Driver
initial-size: 1
min-idle: 1
max-active: 20
max-wait: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
filter:
stat:
enabled: false
wall:
enabled: true
web-stat-filter:
enabled: false
stat-view-servlet:
enabled: false
session:
store-type: none
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
global-config:
logic-delete-value: 0
logic-not-delete-value: 1
mapper-locations: classpath*:/mapper/*.xml
2.新建DataSourceContextHolder 用于设置,获取,清空 当前线程内的数据源变量。
/**
* @program: boss
* @description:
* @author: KingdomCoder
* @create: 2019/1/11 下午10:29
**/
public class DataSourceContextHolder {
private static final ThreadLocal CONTEXTHOLDER = new InheritableThreadLocal<>();
/**
* 设置数据源
*/
public static void setDataSource(String db) {
CONTEXTHOLDER.set(db);
}
/**
* 取得当前数据源
*/
public static String getDataSource() {
return CONTEXTHOLDER.get();
}
/**
* 清除上下文数据
*/
public static void clear() {
CONTEXTHOLDER.remove();
}
}
3.新建MultipleDataSource
实现 AbstractRoutingDataSource
类。重写determineCurrentLookupKey()
,通过 DataSourceContextHolder
获取数据源变量,用于当作lookupKey
取出指定的数据源。
/**
* @program: boss
* @description:
* @author: KingdomCoder
* @create: 2019/1/11 下午10:26
**/
public class MultipleDataSourceConfig extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSource();
}
}
4.新建DataSourceEnum
用于存放数据源名称。
/**
* @program: boss
* @description:
* @author: KingdomCoder
* @create: 2019/1/11 下午10:30
**/
public enum DataSourceEnum {
DATASOURCE1("boss"),
DATASOURCE2("workstation");
DataSourceEnum(String value) {
this.value = value;
}
@Getter
private String value;
}
5.新建并配置DataSourceConfig
/**
* @program: boss
* @description:
* @author: KingdomCoder
* @create: 2019/1/11 下午10:30
**/
@Configuration
public class DataSourceConfig {
@Bean("datasource1")
@ConfigurationProperties("spring.datasource.druid.datasource1")
public DataSource datasource1() {
return DruidDataSourceBuilder.create().build();
}
@Bean("datasource2")
@ConfigurationProperties("spring.datasource.druid.datasource2")
public DataSource datasource2() {
return DruidDataSourceBuilder.create().build();
}
@Bean("multipleDataSource")
@Primary
public DataSource multipleDataSource(@Qualifier("datasource1") DataSource datasource1,
@Qualifier("datasource2") DataSource datasource2) {
MultipleDataSourceConfig multipleDataSource = new MultipleDataSourceConfig();
Map
6.新建并配置MybatisConfig
:
/**
* @program: boss
* @description:
* @author: KingdomCoder
* @create: 2019/1/11 下午10:30
**/
@Configuration
@MapperScan(basePackages = "com.xxx.xxx.xx.mapper")
public class MybatisConfig {
@Autowired
private DataSource multipleDataSource;
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
@Bean("sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
sqlSessionFactory.setDataSource(multipleDataSource);
sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mapper/*/*Mapper.xml"));
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setJdbcTypeForNull(JdbcType.NULL);
configuration.setCacheEnabled(false);
sqlSessionFactory.setConfiguration(configuration);
sqlSessionFactory.setPlugins(new Interceptor[]{
paginationInterceptor() //添加分页功能
});
return sqlSessionFactory.getObject();
}
}
7.编写选择数据源注解:
/**
* @program: boss
* @description:
* @author: KingdomCoder
* @create: 2019/1/11 下午10:30
**/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
DataSourceEnum value() default DataSourceEnum. DATASOURCE1;
}
8.编写切面Aop类DataSourceAspect
:
/**
* @program: boss
* @description:
* @author: KingdomCoder
* @create: 2019/1/11 下午10:30
**/
@Component
@Slf4j
@Aspect
@Order(-1)
public class DataSourceAspect {
@Pointcut("@within(com.xxx.xxxx.xxx.dbselection.DataSource) || @annotation(com.xxxx.xxxx.xxxx.DataSource)")
public void pointCut() {
}
@Before("pointCut() && @annotation(dataSource)")
public void doBefore(DataSource dataSource) {
log.info("选择数据源---" + dataSource.value().getValue());
DataSourceContextHolder.setDataSource(dataSource.value().getValue());
}
@After("pointCut()")
public void doAfter() {
DataSourceContextHolder.clear();
}
}
恭喜你只要在方法或者类上加上注解@DataSource(DataSourceEnum. DATASOURCE1)
或者@DataSource(DataSourceEnum. DATASOURCE2)
可以愉快的选择自己想要操作的数据源了。