如何为AbstractRoutingDataSource安全频繁的DataSource切换?

我根据这篇文章为Spring + Hibernate实现了Dynamic DataSource Routing。 我有几个具有相同结构的数据库,我需要选择哪个数据库将运行每个特定的查询。

在localhost上一切正常,但我担心这将如何在真实的网站环境中保持。 他们使用一些静态上下文持有者来确定要使用的数据源:

public class CustomerContextHolder { private static final ThreadLocal contextHolder = new ThreadLocal(); public static void setCustomerType(CustomerType customerType) { Assert.notNull(customerType, "customerType cannot be null"); contextHolder.set(customerType); } public static CustomerType getCustomerType() { return (CustomerType) contextHolder.get(); } public static void clearCustomerType() { contextHolder.remove(); } } 

它被包装在一些ThreadLocal容器中,但究竟是什么意思呢? 当两个Web请求并行调用此代码时会发生什么:

 CustomerContextHolder.setCustomerType(CustomerType.GOLD); // List goldItems = catalog.getItems(); 

是否每个Web请求都包装在Spring MVC中自己的线程中? CustomerContextHolder.setCustomerType()更改是否会对其他Web用户可见? 我的控制器有synchronizeOnSession=true

如何确保在我为当前用户运行所需查询之前,没有其他人会切换数据源?

谢谢。

是否每个Web请求都包装在Spring MVC中自己的线程中?

是的,但这与Spring MVC无关,容器正在这样做(容器有一个线程池,并选择其中一个来处理每个请求)。

CustomerContextHolder.setCustomerType()更改是否会对其他Web用户可见?

不是。根据定义, ThreadLocal是一个线程的本地。 来自javadoc:

该类提供线程局部变量。 这些变量与它们的正常对应物的不同之处在于,访问一个变量的每个线程(通过其getset方法)都有自己独立初始化的变量副本。 ThreadLocal实例通常是希望将状态与线程相关联的类中的私有静态字段(例如,用户ID或事务ID)。

您在ThreadLocal set的内容对其他线程不可见。 你应该没事