在spring中设置和获取会话绑定属性

时间:2012-10-02 14:43:36

标签: java spring thread-safety multi-tenant

我在Spring上关注了dynamic datasource routing教程的教程。为此,我必须扩展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)请求值来知道要使用什么数据源,它是{{ 1}}确实,因为它为这个线程提供了一个新值。

有没有办法实现Session-bounded而不是Thread-bounded?

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

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

1 个答案:

答案 0 :(得分: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
    }
}