0

我在 Spring中遵循了关于动态数据源路由教程的教程。为此,我必须扩展 AbstractRoutingDataSource 以告诉 spring 要获取哪个数据源,所以我这样做:

public class CustomRouter extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return CustomerContextHolder.getCustomerType();
    }
}

一切都很好,直到我找到负责保持 customerType 值的类(在整个会话期间它应该是相同的):

    public class CustomerContextHolder {

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

        public static void setCustomerType(Integer customerType) {
            contextHolder.set(customerType);
        } 
        public static Integer getCustomerType() {
            return (Integer) contextHolder.get();
        }
        public static void clearCustomerType() {
            contextHolder.remove();
        }
    }

这会创建一个线程绑定变量customerType,但是我有一个带有spring 和JSF 的Web 应用程序,我认为不是线程而是会话。所以我用线程A(View)在登录页面中设置它,但随后线程B(Hibernate)请求该值以知道要使用哪个数据源,null确实如此,因为它对该线程有一个新的值。

有没有办法做到会话有界而不是线程有界?

到目前为止我尝试过的事情:

  • 在视图中注入 CustomRouter 以在会话中设置它:不工作,它会导致依赖项中的循环
  • 用整数替换ThreadLocal:不起作用,该值始终由最后登录的用户设置
4

1 回答 1

1

FacesContext.getCurrentInstance()在工作吗?如果是这样,那么您可以尝试这样做:

public class CustomerContextHolder { 

    private static HttpSession getCurrentSession(){
             HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance()
                 .getExternalContext().getRequest();

             return request.getSession();
    }

    public static void setCustomerType(Integer customerType) {

       CustomerContextHolder.getCurrentSession().setAttribute("userType", customerType);

    }

    public static Integer getCustomerType() {

        return (Integer) CustomerContextHolder.getCurrentSession().getAttribute("userType");
    }

    public static void clearCustomerType() {
        contextHolder.remove(); // You may want to remove the attribute in session, dunno
    }
}
于 2012-10-02T15:47:10.847 回答