Никогда не помещайте состояние в контроллер, как в сервлете, он будет глобальным для всех, и доступ к нему должен быть синхронизирован.В общем, это хорошее правило, чтобы просто не помещать ничего изменяемого в поле контроллера.Вы даже не должны помещать бизнес-логику в контроллер, вы должны вызывать Objects из сервисного уровня, выполняющего всю работу с мощными сервисами.
Чтобы решить вашу проблему, вы можете определить интерфейс под названием QuestSession
, которыйбудет действовать как прокси для пользовательского разговорного состояния.Лучше, если вы реализуете пограничные проверки.(Я думаю, индекс и оценка не могут быть отрицательными, например).
public interface QuestSession {
public int getIndex();
public void setIndex(int index);
public int getScore();
public void setScore(int score);
}
Затем вы просто передаете этот интерфейс туда, где он вам нужен, например:
public ModelAndView showQuestionForm2(
@ModelAttribute("questionForm") QuestionForm questionForm,
BindingResult result, QuestSession session) {
Чтобы сделатьэто работает, вы должны создать QuestSessionImpl
и добавить в свою конфигурацию XML.
<bean id="questSessionImpl" class="package.QuestSessionImpl" scope="session">
<aop:scoped-proxy />
</bean>
aop: scoped-proxy , это бит аспектно-ориентированного программирования, который выполняетмагия прокси вашего класса, чтобы каждая сессия разговаривала с другим объектом.Вы даже можете использовать @Autowired
в поле «Контроллер», и каждый сеанс будет по-прежнему получать разные объекты.
Я не знаю, как выразить это аннотациями, если кто-то читает это, знает, пожалуйста, совет.
Слово предупреждения.Даже доступ к сеансу не является потокобезопасным.Конечно, это менее опасно, чем глобальный общий доступ к одному полю, но все же возможно, что пользователь открывает две вкладки браузера или окна, создающие условия гонки.Вы начинаете чувствовать всю боль от этого с AJAX, так как многие асинхронные запросы могут объединяться.Даже если вы не используете AJAX, вы можете добавить правильную синхронизацию.