本文环境是SpringBoot + Spring + Mybatis Plus
1.配置多数据源
2.使用注解来标记目标数据源
3.使用AOP来动态切换数据源
application.yml
#app
server:
port: 8085
#spring
spring:
profiles:
active: dev
datasource:
type: com.alibaba.druid.pool.DruidDataSource
channel:
name: bole_channel
# druid相关配置
# 监控统计拦截的filters
filters: stat
# -log4j
# -wall
# 配置初始化大小/最小/最大
initial-size: 1
min-idle: 1
max-active: 20
# 获取连接等待超时时间
max-wait: 60000
# 间隔多久进行一次检测,检测需要关闭的空闲连接
time-between-eviction-runs-millis: 60000
# 一个连接在池中最小生存的时间
min-evictable-idle-time-millis: 300000
validation-query: SELECT 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
# 打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
driver-class-name: com.mysql.jdbc.Driver
qlm:
name: bole_qlm
# druid相关配置
# 监控统计拦截的filters
filters: stat
# -log4j
# -wall
# 配置初始化大小/最小/最大
initial-size: 1
min-idle: 1
max-active: 20
# 获取连接等待超时时间
max-wait: 60000
# 间隔多久进行一次检测,检测需要关闭的空闲连接
time-between-eviction-runs-millis: 60000
# 一个连接在池中最小生存的时间
min-evictable-idle-time-millis: 300000
validation-query: SELECT 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
# 打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
pool-prepared-statements: false
max-pool-prepared-statement-per-connection-size: 20
driver-class-name: com.mysql.jdbc.Driver
#mybatis
mybatis-plus:
# 如果是放在src/main/java目录下 classpath:/com/yourpackage/*/dao/*Mapper.xml
# 如果是放在resource目录 classpath:/dao/*Mapper.xml
mapper-locations: classpath*:/mapper/*Mapper.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.agent_web.api.entity
typeEnumsPackage: com.agent_web.api.enums
global-config:
db-config:
#主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
id-type: AUTO
# 字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
field-strategy: not_empty
# 驼峰下划线转换
column-underline: true
# mp2.3+ 全局表前缀 mp_
# table-prefix: mp_
# 刷新mapper 调试神器
# refresh-dao: true
# 数据库大写下划线转换
# capital-mode: true
# Sequence序列接口实现类配置
# key-generator: com.baomidou.mybatisplus.incrementer.OracleKeyGenerator
#逻辑删除配置(下面3个配置)
logic-delete-value: 1
logic-not-delete-value: 0
# sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector
db-type: mysql
refresh: true
# sql-injector: com.baomidou.mybatisplus.core.injector.ISqlInjector
# 自定义填充策略接口实现
# meta-object-handler: com.baomidou.springboot.MyMetaObjectHandler
configuration:
# 配置返回数据库(column下划线命名&&返回java实体是驼峰命名),自动匹配无需as(没开启这个,SQL需要写as: select user_id as userId)
map-underscore-to-camel-case: true
cache-enabled: false
# type-enums-package: com.shengya.service.bean.enums
application-dev.xml
spring:
# 数据源
datasource:
channel:
url: jdbc:mysql://localhost:3306/channel?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull
username: admin
password: 111111
qlm:
url: jdbc:mysql://localhost:3306/qlm?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull
username: admin
password: 111111
继承Spring的AbstractRoutingDataSource类,该类相当于一个DataSource路由,可以根据key值自动切换对应数据源
package com.agent_web.api.config;
import com.agent_web.api.utils.DataSourceHolder;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* @author wise
* @version 2.0.0
* @createdate 2018-07-23 15:42.
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceHolder.getDataSource();
}
}
多数据源初始化:
package com.agent_web.api.config;
import com.agent_web.api.enums.CommonEnum;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.util.HashMap;
/** 多数据配置(初始化)
* @author wise
* @createdate 2018-07-23 15:41.
*/
@Configuration
public class MultipleDataSourceConfig {
@Bean(name = "dataSourceChannel")
@ConfigurationProperties(prefix = "spring.datasource.channel")
public DataSource channelDataSource(){
return new DruidDataSource();
}
@Bean(name = "dataSourceQlm")
@ConfigurationProperties(prefix = "spring.datasource.qlm")
public DataSource qlmDataSource(){
return new DruidDataSource();
}
@Primary
@Bean(name = "dynamicDataSource")
public DataSource dynamicDataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
//配置默认数据源
dynamicDataSource.setDefaultTargetDataSource(channelDataSource());
//初始化数据源
HashMap
package com.agent_web.api.annotation;
import com.agent_web.api.enums.CommonEnum;
import java.lang.annotation.*;
/**
* @author wise
* @createdate 2018-08-23 11:29.
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
CommonEnum.DataSourceType value() default CommonEnum.DataSourceType.CHANNEL;
}
CommonEnum:
public enum DataSourceType{
CHANNEL,QLM
}
package com.agent_web.api.aop;
import com.agent_web.api.annotation.DataSource;
import com.agent_web.api.enums.CommonEnum;
import com.agent_web.api.utils.DataSourceHolder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* @author wise
* @createdate 2018-07-23 17:40.
*/
@Component
@Aspect
public class DataSourceAspect {
/** 设定切面
* @author wise
* @date 2018/7/23 0027 17:42
* @param
* @return void
*/
@Pointcut("@annotation(com.agent_web.api.annotation.DataSource)")
private void pointcut() {
}
/** 在执行方法体之前切换数据源
* @author wise
* @date 2018/7/23 0027 17:45
* @param point
* @return void
*/
@Before("pointcut()&&@annotation(com.agent_web.api.annotation.DataSource)")
public void before (JoinPoint point) {
try {
//获取默认数据源
CommonEnum.DataSourceType dataSourceType = CommonEnum.DataSourceType.CHANNEL;
String methodName = point.getSignature().getName();
//获取参数类型
Class[] parameterTypes = ((MethodSignature) point.getSignature()).getParameterTypes();
Method method = point.getTarget().getClass().getMethod(methodName, parameterTypes);
//获取方法上的注解
DataSource methodAnnotation = method.getAnnotation(DataSource.class);
if (methodAnnotation != null && methodAnnotation.value() != null) {
//设置目标数据源
dataSourceType = methodAnnotation.value();
}
//切换数据源
DataSourceHolder.setDataSource(dataSourceType.name());
} catch (Exception e){
e.printStackTrace();
}
}
/** 清除数据源
* @author wise
* @date 2018/7/23 0027 17:50
* @param point
* @return void
*/
@After("pointcut()&&@annotation(com.agent_web.api.annotation.DataSource)")
public void after(JoinPoint point){
DataSourceHolder.clearDataSource();
}
}
DataSourceHolder:
这里使用ThreadLocal来存储数据源,保证当前线程的数据源是隔离状态的
package com.agent_web.api.utils;
import lombok.extern.log4j.Log4j2;
/** 数据源切换类
* @author wise
* @createdate 2018-07-23 17:24.
*/
@Log4j2
public class DataSourceHolder {
private static final ThreadLocal contextHolder = new ThreadLocal();
public static void setDataSource(String dbType){
log.info("切换数据源: {}" ,dbType);
contextHolder.set(dbType);
}
public static String getDataSource(){
return contextHolder.get();
}
public static void clearDataSource(){
contextHolder.remove();
}
}
因为我们要使用自定义的数据观配置,所以需要关掉SpringBoot的自动数据源配置
exclude = DataSourceAutoConfiguration.class
package com.agent_web.api;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class AgentWebApplication {
public static void main(String[] args) {
SpringApplication.run(AgentWebApplication.class, args);
}
}
在SpringMVC使用过动态数据源切换的小伙伴应该发现,其实都是一样的,只不过是SpringBoot的配置方式发生了改变而已,以前我们在XML中配置多数据源,现在换到了yml中,以上所有代码都经过了测试,如有问题,请您私信我
版权声明:本文为博主原创文章,转载请注明出处(https://blog.csdn.net/F1004145107/article/details/82022683)