栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springboot

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springboot

多数据源配置
# 主库数据源配置
spring.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.master.url=jdbc:mysql://192.168.1.11:3308/redenvelopes?useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true&allowMultiQueries=true
spring.datasource.master.username=redenvelopes
spring.datasource.master.password=USSfro2Y2vSoxj4nOH8JA4zk9tmINs7i6bOKQgcu0cQ1SFHP74CIGdHzsxZaQlDAHxRs7MMkj1ilDeLAnOBBzw==
spring.datasource.master.initial-size=30
spring.datasource.master.max-active=300
spring.datasource.master.min-idle=20
spring.datasource.master.time-between-eviction-runs-millis=60000
spring.datasource.master.min-evictable-idle-time-millis=300000
spring.datasource.master.validation-query=select 1
spring.datasource.master.test-while-idle=true
spring.datasource.master.test-on-borrow=true
spring.datasource.master.test-on-return=false
spring.datasource.master.max-wait=60000
spring.datasource.master.filters=stat,config
spring.datasource.master.filter.stat.enabled=true
spring.datasource.master.filter.stat.slow-sql-millis=100000
spring.datasource.master.filter.stat.log-slow-sql=true
spring.datasource.master.connection-properties=config.decrypt=true;config.decrypt.key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALPq2OsSVb075O3ELXlC82KF2YdKtVv01y4tu7wZN11b3mw6zZDIdh+ZRU3S+Kui6wVE7XRsupbroIJcspW40eMCAwEAAQ==
# 从库数据源配置
spring.datasource.readonly.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.readonly.url=jdbc:mysql://192.168.1.11:3308/redenvelopes?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
spring.datasource.readonly.username=devsup01
spring.datasource.readonly.password=DaSw+Rg9zM508O+H5b2a32mE0m6Qy1v2YtSl0ti6QTtJOXjKWsQhkdCDIRiK9gV1/hY7hYrpGe403yom+um4PQ==
spring.datasource.readonly.initial-size=30
spring.datasource.readonly.max-active=300
spring.datasource.readonly.min-idle=20
spring.datasource.readonly.time-between-eviction-runs-millis=60000
spring.datasource.readonly.min-evictable-idle-time-millis=300000
spring.datasource.readonly.validation-query=select 1
spring.datasource.readonly.test-while-idle=true
spring.datasource.readonly.test-on-borrow=true
spring.datasource.readonly.test-on-return=false
spring.datasource.readonly.max-wait=60000
spring.datasource.readonly.filters=stat,config
spring.datasource.readonly.filter.stat.enabled=true
spring.datasource.readonly.filter.stat.slow-sql-millis=100000
spring.datasource.readonly.filter.stat.log-slow-sql=true
spring.datasource.readonly.connection-properties=config.decrypt=true;config.decrypt.key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMzWx3SAo7gF2TguEJQjL5TFON47dTAJCU0Va3oygJ34OJRHjlPeOcla7eaxp40DlhH/MprUlgmLWCvXNEtEL8UCAwEAAQ==

配置DataSource

@Configuration
public class DataSourceConfig {

    public final static String DS_MASTER = "master";

    public final static String DS_READonLY = "readonly";

    protected Logger logger = LoggerFactory.getLogger(getClass());

    
    @Bean(name = DS_MASTER)
    @ConfigurationProperties(prefix = "spring.datasource.master") // application.properteis中对应属性的前缀
    public DataSource dataSource1() {
        logger.info("Load datasource of {} ...", DS_MASTER);
        return DruidDataSourceBuilder.create().build();
    }

    
    @Bean(name = DS_READONLY)
    @ConfigurationProperties(prefix = "spring.datasource.readonly") // application.properteis中对应属性的前缀
    public DataSource dataSource2() {
        logger.info("Load datasource of {} ...", DS_READONLY);
        return DruidDataSourceBuilder.create().build();
    }


    @Autowired
    @Lazy
    @Qualifier(DS_MASTER)
    DataSource master;

    @Autowired
    @Lazy
    @Qualifier(DS_READONLY)
    DataSource readonly;

    
    @Bean
    @Primary
    public DataSource dataSource() {
        RdpRoutingDataSource rdpRoutingDataSource = new RdpRoutingDataSource();
        // 默认数据源
        rdpRoutingDataSource.setDefaultTargetDataSource(master);
        // 配置多数据源
        Map dsMap = new HashMap<>(5);
        dsMap.put(DS_MASTER, master);
        dsMap.put(DS_READONLY, readonly);

        rdpRoutingDataSource.setTargetDataSources(dsMap);
        return rdpRoutingDataSource;
    }
动态选择DataSource

动态数据源线程上下文

public class DataSourceContextHolder {
   
   protected static Logger logger = LoggerFactory.getLogger(DataSourceContextHolder.class);

    
    public static final String DEFAULT_DS = "master";

    private static final ThreadLocal contextHolder = new ThreadLocal<>();

    
    public static void setDB(String dbType) {
       logger.debug("Try to select datasource:{}", dbType); 
        contextHolder.set(dbType);
    }

    // 获取数据源名
    public static String getDB() {
        return (contextHolder.get());
    }

    // 清除数据源
    public static void clearDB() {
       logger.debug("Try to clear datasource:{}", getDB()); 
        contextHolder.remove();
    }
}

自定义类继承 AbstractRoutingDataSource,重写 determineCurrentLookupKey(),返回数据源的唯一标识;

public class RdpRoutingDataSource extends AbstractRoutingDataSource {
	
	protected static Logger logger = LoggerFactory.getLogger(RdpRoutingDataSource.class);

    @Override
    protected Object determineCurrentLookupKey() {
    	logger.debug("当前数据源: {}", StringUtils.isEmpty(DataSourceContextHolder.getDB())? "default" : DataSourceContextHolder.getDB());
        return DataSourceContextHolder.getDB();
    }
}
注解(主动配置选择)

用于主动选择数据源

@Retention(RetentionPolicy.RUNTIME)
@Target({
        ElementType.METHOD
})
//@Inherited
public @interface DsSelector {
    String value() default DataSourceContextHolder.DEFAULT_DS;
}
AOP 拦截切换数据源

每次对@DsSelector注解的方法去数据源上下文中获取当前线程的连接的数据源


@EnableAspectJAutoProxy
@Order(1)
@Aspect
@Component
public class RdpDataSourceAspect {
    private Logger logger = LoggerFactory.getLogger(RdpDataSourceAspect.class);

	@Around("execution(* cn.swiftpass..service.impl.*.*(..)) && @annotation(DsSelector)")
    public Object around(ProceedingJoinPoint joinPoint){
	    try {
            String dataSource = "";
            // 当前class
            Class className = joinPoint.getTarget().getClass();
            // 当前方法名
            String methodName = joinPoint.getSignature().getName();
            // 方法的参数的类型
            Class[] argClass = ((MethodSignature)joinPoint.getSignature()).getParameterTypes();

            try {
                // 方法对象
                Method method = className.getMethod(methodName, argClass);
                // 判断是否存在@DsSelector注解
                if (method.isAnnotationPresent(DsSelector.class)) {
                    DsSelector annotation = method.getAnnotation(DsSelector.class);
                    // 取出指定的数据源名
                    dataSource = annotation.value();
                }
            } catch (Exception e) {
                logger.warn("RdpDataSourceAspect.around exception", e);
            }
            // 切换数据源
            DataSourceContextHolder.setDB(dataSource);
            return joinPoint.proceed();
        } catch (Throwable t) {
            logger.error("未知异常", t);
            return null;
        } finally {
            // 清楚当前线程的数据源
            DataSourceContextHolder.clearDB();
        }
    }

}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/759239.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号