Что произойдет, если я забуду пометить Spring SessionStatus как «Complete»? - PullRequest
17 голосов
/ 19 мая 2009

В Spring MVC предположим, что я определяю SessionAttribute, используя тег @SessionAttribute, например:

@SessionAttributes(value = "myModel")
public class MyController{
   ...
}

Предположим, что я забыл вызвать status.setComplete () для SessionStatus следующим образом:

@RequestMapping(method = RequestMethod.POST)
public void doSomething(@ModelAttribute("myModel") MyModel model, SessionStatus status){
   ...
   //status.setComplete(); <-- Never gets called
}

Модель останется в сессии навсегда? Будет ли он когда-либо очищен, или сессия будет расти все больше и больше, когда пользователь перемещается по сайту?

Ответы [ 3 ]

22 голосов
/ 17 февраля 2012

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

Чтобы уточнить раз и навсегда, мы можем взглянуть на исходный код Spring MVC 3.1.0 RELEASE .

Интерфейс org.springframework.web.bind.support.SessionAttributeStore предоставляет следующие методы:

void storeAttribute(WebRequest request, String attributeName, Object attributeValue);

Object retrieveAttribute(WebRequest request, String attributeName);

void cleanupAttribute(WebRequest request, String attributeName);

Реализация по умолчанию: org.springframework.web.bind.support.DefaultSessionAttributeStore

Выполнив « Открытая иерархия вызовов » на cleanupAttribute () в Eclipse, мы можем видеть, что метод вызывается двумя различными потоками:

1) org.springframework.web.method.annotation.ModelFactory

public void updateModel(NativeWebRequest request, ModelAndViewContainer mavContainer) throws Exception {

        if (mavContainer.getSessionStatus().isComplete()){
            this.sessionAttributesHandler.cleanupAttributes(request);
        }
        else {
            this.sessionAttributesHandler.storeAttributes(request, mavContainer.getModel());
        }

        if (!mavContainer.isRequestHandled()) {
            updateBindingResult(request, mavContainer.getModel());
        } 
    }

2) org.springframework.web.bind.annotation.support.HandlerMethodInvoker

public final void updateModelAttributes(Object handler, Map<String, Object> mavModel,
            ExtendedModelMap implicitModel, NativeWebRequest webRequest) throws Exception {

        if (this.methodResolver.hasSessionAttributes() && this.sessionStatus.isComplete()) {
            for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
                this.sessionAttributeStore.cleanupAttribute(webRequest, attrName);
            }
        }
...
}

Понятно, что в обоих случаях атрибут сеанса удаляется только при вызове this.sessionStatus.isComplete () .

Я копался в коде DefaultSessionAttributeStore . Под капотом он получает реальный объект HTTP Session для хранения атрибутов, поэтому к ним потенциально могут обращаться другие контроллеры в одном сеансе.

Так что нет, атрибуты сеанса не удаляются после чистого POST.

12 голосов
/ 02 июня 2009

РЕДАКТИРОВАТЬ # 2: Обратите внимание, что этот ответ больше не является правильным. См. @ doanduyhai ответ ниже.

РЕДАКТИРОВАТЬ: Обратите внимание, что это для Spring 2.5 и может, но не обязательно гарантирует, что то же самое для Spring 3.x. Дважды проверьте документы!

Это соответствует тому, что сказал @ Гэндальф.

Контроллеры форм моделируют срок службы запроса формы, от начального просмотра формы до отправки формы. После отправки формы работа контроллера формы будет выполнена, и он удалит объект команды из сеанса.

Итак, чтобы сохранить объект команды в сеансе между рабочими процессами формы, вам нужно будет управлять сеансом вручную. После чистого POST объект удаляется из сеанса.

Короче говоря, я считаю, что метод setComplete () является хорошей практикой, но не обязательно обязательным.

РЕДАКТИРОВАТЬ : Я просто заглянул в свою весеннюю книгу, чтобы подтвердить это. Я процитирую это:

Когда @SessionAttribute не используется, новый объект команды будет создан на каждый запрос, даже при рендеринге Форма снова из-за ошибок привязки. Если эта аннотация включена, Объект команды будет сохранен в сеанс для последующего использования, до Форма завершается успешно. затем этот объект команды будет очищен из сессии. Обычно это используется, когда объект команды является постоянный объект, который должен быть одинаковые для разных запросов для отслеживания изменений.

По сути, это то, что я говорил выше. Он сохраняет его в сеансе до тех пор, пока вы либо A) не вызовете setComplete (), ни B), когда контроллер успешно завершит POST.

1 голос
/ 19 мая 2009

Есть ли какая-то причина, почему вы хотели бы сделать это?

из этой темы: @ SessionAttribute Problem

@SessionAttributes работает так же, как sessionForm SimpleFormController. Он помещает команду (или для @SessionAttributes любого объекта) в сеанс на время между первым и последним запросом (большую часть времени - начальный GET и последний POST). После этого материал удаляется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...