Подтвердить что ты не робот

Что произойдет, если я забуду отметить Spring SessionStatus как "Полный"?

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

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

4b9b3361

Ответ 1

EDIT # 2: Обратите внимание, что этот ответ больше не верен. См. @doanduyhai answer ниже.

EDIT: Обратите внимание, что это для Spring 2.5 и может, но не обязательно гарантирует, что это будет для Spring 3.x. Дважды проверьте документы!

Это в соответствии с тем, что сказал @Gandalf.

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

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

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

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

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

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

Ответ 2

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

Чтобы уточнить раз и навсегда, мы можем посмотреть исходный код 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.

Ответ 3

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

из этой темы: @Задача SessionAttribute

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