Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在spring中设置和获取会话绑定属性_Java_Spring_Thread Safety_Multi Tenant - Fatal编程技术网

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

Java 在spring中设置和获取会话绑定属性,java,spring,thread-safety,multi-tenant,Java,Spring,Thread Safety,Multi Tenant,我在春季学习了一个教程。为此,我必须扩展AbstractRoutingDataSource来告诉spring要获取哪个数据源,所以我: public class CustomRouter extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return CustomerContextHolder.getCustomerType()

我在春季学习了一个教程。为此,我必须扩展AbstractRoutingDataSource来告诉spring要获取哪个数据源,所以我:

public class CustomRouter extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return CustomerContextHolder.getCustomerType();
    }
}
在我找到负责保存customerType值的类之前,一切都很顺利(在整个会话期间应该是相同的):

公共类CustomerContextHolder{
private static final ThreadLocal contextHolder=new ThreadLocal();
公共静态无效setCustomerType(整型customerType){
contextHolder.set(customerType);
} 
公共静态整数getCustomerType(){
返回(整数)contextHolder.get();
}
公共静态无效clearCustomerType(){
contextHolder.remove();
}
}
这将创建一个线程绑定的变量customerType,但我有一个带有spring和JSF的web应用程序,我不认为是带有线程的,而是带有会话的。因此,我在登录页面中使用threadA(视图)设置它,但是threadB(Hibernate)请求该值以了解要使用的数据源,它实际上是
null
,因为它为该线程提供了一个新值

有没有什么方法可以让它以会话为界而不是线程为界

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

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

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
    }
}

为什么hibernate在另一个线程中执行?不应该吗?当我调试DAO方法时,我看到每次都有不同的线程访问该方法。这是错误的吗?据我所知,servlet容器对每个请求使用一个线程,这意味着当发出HTTP请求时,将创建一个线程或从池中检索一个线程来为其提供服务,并且只有一个线程。因此,只有当一个线程服务于一个不同的请求时,一个不同的线程访问该方法才是可行的。这就是为什么它有不同的值,因为对于一个新线程,我想会创建一个新的ThreadLocal。因此,我需要以某种方式将其存储在会话中,即请求之间的持久性线程在新线程运行时不会创建本地线程。相反,它存储一个引用线程的新值。
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
    }
}