springboot基于栈结构实现数据源切换

在这里插入图片描述

先说问题

先说下网上有很多文章写很多demo,参考博客:https://blog.csdn.net/zl_momomo/article/details/82851134,下面是核心代码:

  • 首先定义一个ThrealLocal String类型来存储数据源
    在这里插入图片描述
  • 做一个切面,设置这个数据源,方法执行完,把ThreadLocal给清理掉。
    在这里插入图片描述
  • spring 从当前ThreadLocal获取数据源
    在这里插入图片描述
    这个可以满足我们大多数场景,来看一个问题:

在这里插入图片描述
思考下C方法会是哪个数据源?
答案是方法c会执行默认数据源,但是问题是我们在调用c方法上明明标记了a数据源,不应该走a数据源么。方法c执行完,ThreadLocal就没有了,其实我们要还能从ThreadLocal中获取到a数据源。

基于这样的场景好像,只存一个string结构就不满足了。

这样就考虑到,既然是切到注解上,只有这个注解的方法执行完了,才能把ThreadLocal的值给删掉,于是就想到了栈结构。

解决问题

public final class DynamicDataSourceContextHolder {

    private static final ThreadLocal<Deque<String>> LOOKUP_KEY_HOLDER = new NamedThreadLocal<Deque<String>>("dynamic-datasource") {
        @Override
        protected Deque<String> initialValue() {
            return new ArrayDeque<>();
        }
    };

    private DynamicDataSourceContextHolder() {
    }

    /**
     * 获得当前线程数据源
     *
     * @return 数据源名称
     */
    public static String peek() {
        return LOOKUP_KEY_HOLDER.get().peek();
    }

    /**
     * 设置当前线程数据源
     * <p>
     * 如非必要不要手动调用,调用后确保最终清除
     * </p>
     *
     * @param ds 数据源名称
     */
    public static void push(String ds) {
        LOOKUP_KEY_HOLDER.get().push(StringUtils.isEmpty(ds) ? "" : ds);
    }

    /**
     * 清空当前线程数据源
     * <p>
     * 如果当前线程是连续切换数据源 只会移除掉当前线程的数据源名称
     * </p>
     */
    public static void poll() {
        Deque<String> deque = LOOKUP_KEY_HOLDER.get();
        deque.poll();
        if (deque.isEmpty()) {
            LOOKUP_KEY_HOLDER.remove();
        }
    }

    /**
     * 强制清空本地线程
     * <p>
     * 防止内存泄漏,如手动调用了push可调用此方法确保清除
     * </p>
     */
    public static void clear() {
        LOOKUP_KEY_HOLDER.remove();
    }
}
  1. 数据源注解拦截器里面调用push、poll方法,控制添加、删除元素。
  2. spring获取动态数据源只需要调用peek方法,不需要弹出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值