Доступ к атрибуту сеанса Spring MVC

Есть ли способ в Spring 3.0 получить доступ к HttpSession без включения его в сигнатуру метода? Что я действительно хочу сделать, так это иметь возможность передавать значения из HttpSession, которые МОГУТ БЫТЬ нулевыми.

Что-то вроде этого:

@RequestMapping("/myHomePage")
public ModelAndView show(UserSecurityContext ctx) {}

вместо этого:

@RequestMapping("/myHomePage")
public ModelAndView show(HttpSession session) {
      UserSecurityContext ctx = (UserSecurityContext) session.getAttribute("userSecurityCtx");
}

person Mark    schedule 06.02.2010    source источник
comment
связанные: stackoverflow.com/questions/3621266/   -  person Bozho    schedule 01.09.2010
comment
Вот билет Spring #SPR-4452 для этого. Проголосуйте за билет для более быстрого решения.   -  person Johan Sjöberg    schedule 07.09.2011


Ответы (3)


Аннотация @SessionAttribute, упомянутая @uthark, не подходит для этой задачи — я тоже так думал, но немного чтения показывает обратное:

Атрибуты сеанса, указанные с помощью этой аннотации, соответствуют атрибутам модели конкретного обработчика, которые прозрачно сохраняются в диалоговом сеансе. Эти атрибуты будут удалены, как только обработчик укажет на завершение диалогового сеанса. Поэтому используйте это средство для таких диалоговых атрибутов, которые должны временно храниться в сеансе в ходе диалога определенного обработчика.

Для постоянных атрибутов сеанса, например. объект аутентификации пользователя, вместо этого используйте традиционный метод session.setAttribute. В качестве альтернативы рассмотрите возможность использования возможностей управления атрибутами универсального интерфейса WebRequest.

Другими словами, @SessionAttribute предназначен для хранения объектов MVC-модели диалога в сеансе (в отличие от их хранения в качестве атрибутов запроса). Он не предназначен для использования с произвольными атрибутами сеанса. Как вы обнаружили, это работает только в том случае, если атрибут сеанса всегда присутствует.

Я не знаю никакой другой альтернативы, я думаю, что вы застряли с HttpSession.getAttribute()

person skaffman    schedule 06.02.2010
comment
На самом деле я использовал часть решения @uthark. Чтобы защититься от исключений, вызванных нулевым объектом пользовательского контекста, я поместил ServletFilter впереди, чтобы убедиться, что он заполнен. Я согласен с этим решением для этого конкретного рабочего процесса, но кажется странным, что вы не можете сами обработать нулевое значение, вместо того, чтобы Spring обработал его за вас. Спасибо всем за помощь и понимание. - person Mark; 06.02.2010
comment
@skaffman Есть ли причина, по которой документы не выходят прямо и говорят «контроллер» вместо использования термина handler? - person Kevin Bowersox; 26.05.2016

Вы можете использовать RequestContextHolder:

class SecurityContextHolder {
    public static UserSecurityContext currentSecurityContext() {
        return (UserSecurityContext) 
            RequestContextHolder.currentRequestAttributes()
            .getAttribute("userSecurityCtx", RequestAttributes.SCOPE_SESSION));
    }
}
...
@RequestMapping("/myHomePage")           
public ModelAndView show() {           
    UserSecurityContext ctx = SecurityContextHolder.currentSecurityContext();
}

Для сквозных вопросов, таких как безопасность, этот подход лучше, потому что вам не нужно изменять подписи контроллера.

person axtavt    schedule 06.02.2010
comment
Мне тоже нравится это решение. Это чем-то похоже на шаблон ThreadLocal. Спасибо! - person Mark; 07.02.2010

Да, ты можешь.

@SessionAttributes("userSecurityContext")
public class UserSecurityContext {
}

@RequestMapping("/myHomePage")
public String show(@ModelAttribute("userSecurityContext") UserSecurityContext u) {
    // code goes here.
}

Подробнее см.:

  1. http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/bind/annotation/SessionAttributes.html

  2. http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/bind/annotation/ModelAttribute.html

person uthark    schedule 06.02.2010
comment
Спасибо за ответ. Сначала я добавляю свой контекст безопасности с помощью session.putAttribute(). Когда я пробую ваш код, объект контекста имеет значение null. - person Mark; 06.02.2010
comment
Извините, это сработало, когда я добавил @SessionAttributes(userSecurityContext) в контроллер. Простое добавление его в фактическое pojo UserSecurityContext ничего для меня не дало. Однако из Spring выдается исключение, когда атрибут имеет значение null, чего я пытаюсь избежать. org.springframework.web.HttpSessionRequiredException: требуется атрибут сеанса userSecurityContext — не найден в сеансе - person Mark; 06.02.2010
comment
@Mark Если этот ответ не подходит, переместите принятый флаг (или удалите его), как это предлагается в ответе ниже (автор skaffman). Это вводит в заблуждение, так как многие люди читают только принятый ответ. (просто прочитайте ваш комментарий ниже - ваш звонок!) - person Breaking not so bad; 02.02.2011