Установка и получение атрибута, привязанного к сеансу, весной

Я следовал руководству по динамической маршрутизации источников данных в 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, я не думаю, что с потоками, а с сеансами. Поэтому я установил его на странице входа с потоком A (View), но затем поток B (Hibernate) запрашивает значение, чтобы узнать, какой источник данных использовать, это действительно null , потому что у него новое значение для этого потока.

Есть ли способ сделать это с ограничением сеанса, а не с ограничением потока?

Вещи, которые я пробовал до сих пор:

  • Вставьте CustomRouter в представление, чтобы установить его в сеансе: не работает, вызывает цикл в зависимостях.
  • Замените ThreadLocal целым числом: не работает, значение всегда устанавливается последним пользователем, вошедшим в систему.

person Eugenio Cuevas    schedule 02.10.2012    source источник
comment
почему спящий режим выполняется в другом потоке?   -  person ElderMael    schedule 02.10.2012
comment
Разве это не должно быть? Когда я отлаживаю методы DAO, я вижу, что каждый раз к методу обращается другой поток. Это неправильно?   -  person Eugenio Cuevas    schedule 02.10.2012
comment
Насколько я знаю, контейнеры сервлетов используют поток для каждого запроса, это означает, что при выполнении HTTP-запроса поток создается или извлекается из пула для его обслуживания и только один поток. Таким образом, другой поток, обращающийся к методу, допустим, только если этот поток обслуживает другой запрос.   -  person ElderMael    schedule 02.10.2012
comment
Вот почему он имеет разные значения, потому что для нового потока, я думаю, будет создан новый ThreadLocal. Поэтому мне нужно каким-то образом сохранить его в сеансе, который сохраняется между запросами.   -  person Eugenio Cuevas    schedule 03.10.2012
comment
ThreadLocals не создаются при запуске нового потока. Вместо этого он сохраняет новое значение, слабо ссылающееся на поток.   -  person ElderMael    schedule 03.10.2012


Ответы (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
    }
}
person ElderMael    schedule 02.10.2012