代码之家  ›  专栏  ›  技术社区  ›  serg

如何安全地频繁切换抽象路由数据源?

  •  3
  • serg  · 技术社区  · 14 年前

    我为Spring+Hibernate实现了动态数据源路由,根据 this article . 我有几个具有相同结构的数据库,需要选择运行每个特定查询的数据库。

    在本地主机上一切都可以正常工作,但我担心这会在真实的网站环境中维持下去。他们使用一些静态上下文持有者来确定要使用的数据源:

    public class  CustomerContextHolder {
    
       private static final ThreadLocal<CustomerType> contextHolder =
                new ThreadLocal<CustomerType>();
    
       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();
       }
    }
    

    它被包装在一个线状的容器里,但这究竟意味着什么?当两个Web请求并行调用这段代码时会发生什么:

    CustomerContextHolder.setCustomerType(CustomerType.GOLD);
    //<another user will switch customer type here to CustomerType.SILVER in another request>
    List<Item> goldItems = catalog.getItems();
    

    在SpringMVC中,每个Web请求是否都被包装成自己的线程?威尔 CustomerContextHolder.setCustomerType() 其他Web用户可以看到更改吗?我的控制器有 synchronizeOnSession=true .

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

    谢谢。

    1 回复  |  直到 12 年前
        1
  •  5
  •   Pascal Thivent    14 年前

    在SpringMVC中,每个Web请求是否都被包装成自己的线程?

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

    其他Web用户是否可以看到customerContextHolder.setCustomerType()更改?

    A号 ThreadLocal 按定义是线程的局部。来自JavaDoc:

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

    你什么 设置 在一个 线程本地 对其他线程不可见。你应该没事的