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

Spring Framework 3 и атрибуты сеанса

У меня есть объект формы, который я задал для запроса в обработчике запроса GET в моем контроллере Spring. При первом входе пользователя на страницу необходимо создать новый объект формы и задать запрос. Если пользователь отправляет форму, тогда объект формы заполняется из запроса, и теперь объект формы имеет все атрибуты пользователя givern. Затем форма проверяется и если проверка правильна, форма сохраняется в базе данных. Если форма не подтверждена, я хочу сохранить объект формы в сеанс, а затем перенаправить на страницу обработки запроса GET. Когда запрос перенаправляется на GET-обработчик, тогда он должен проверить, содержит ли сеанс объект формы.

Я выяснил, что в Spring есть аннотация @SessionAttributes ( "form" ), но по какой-то причине следующее не работает, потому что в первый раз форма атрибута сеанса имеет значение null, и она дает ошибку:

org.springframework.web.HttpSessionRequiredException: Session attribute 'form' required - not found in session

Вот мой контроллер:

@RequestMapping(value="form", method=RequestMethod.GET)
public ModelAndView viewForm(@ModelAttribute("form") Form form) {
    ModelAndView mav = new ModelAndView("form");      
    if(form == null) form = new Form();
    mav.addObject("form", form);
    return mav;
}

@RequestMapping(value="form", method=RequestMethod.POST)
@Transactional(readOnly = true)
public ModelAndView saveForm(@ModelAttribute("form") Form form) {
    FormUtils.populate(form, request);
    if(form.validate())
    {
        formDao.save();         
    }
    else 
    {
        return viewForm(form);
    }
    return null;
}
4b9b3361

Ответ 1

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

@SessionAttributes({"form"})
@Controller
public class MyController {

   @RequestMapping(value="form", method=RequestMethod.GET)
   public ModelAndView viewForm(@ModelAttribute("form") Form form) {
       ModelAndView mav = new ModelAndView("form");      
       if(form == null) form = new Form();
       mav.addObject("form", form);
       return mav;
   }

   @RequestMapping(value="form", method=RequestMethod.POST)
   @Transactional(readOnly = true)
   public ModelAndView saveForm(@ModelAttribute("form") Form form) {
      // ..etc etc
   }
}

Обратите внимание, что @SessionAttributes объявляется в классе, а не в методе. Вы можете поместить туда, где хотите, на самом деле, но я думаю, что это имеет больше смысла в классе.

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

Ответ 2

Он выдает исключение, если контроллер вызвал первый раз, даже если добавить класс @SessionAttributes ({ "form" }) в класс. Поэтому добавьте следующий метод populateForm, чтобы исправить это.

@SessionAttributes({"form"})
@Controller
public class MyController {

   @ModelAttribute("form")
   public Form populateForm() {
       return new Form(); // populates form for the first time if its null
   }

   @RequestMapping(value="form", method=RequestMethod.GET)
   public ModelAndView viewForm(@ModelAttribute("form") Form form) {
       ModelAndView mav = new ModelAndView("form");      
       if(form == null) form = new Form();
       mav.addObject("form", form);
       return mav;
   }

   @RequestMapping(value="form", method=RequestMethod.POST)
   @Transactional(readOnly = true)
   public ModelAndView saveForm(@ModelAttribute("form") Form form) {
      // ..etc etc
   }
}

Ответ 3

если нет определенного объекта сеанса, поэтому я думаю, что он будет таким:

@SessionAttributes({"form"})
    @Controller
    public class MyController {
   @RequestMapping(value="form", method=RequestMethod.GET)
   public ModelAndView viewForm() {
       ModelAndView mav = new ModelAndView("form");      
       if(form == null) form = new Form();
       mav.addObject("form", form);
       return mav;
   }

   @RequestMapping(value="form", method=RequestMethod.POST)
   @Transactional(readOnly = true)
   public ModelAndView saveForm(@ModelAttribute("form") Form form) {
      // ..etc etc
   }
}

Ответ 4

@Controller
@SessionAttributes("goal")
public class GoalController {

    @RequestMapping(value = "/addGoal", method = RequestMethod.GET)
    public String addGoal(Model model) {
        model.addAttribute("goal", new Goal(11));
        return "addGoal";
    }

    @RequestMapping(value = "/addGoal", method = RequestMethod.POST)
    public String addGoalMinutes(@ModelAttribute("goal") Goal goal) {
        System.out.println("goal minutes " + goal.getMinutes());
        return "addMinutes";
    }
}

На странице addGoal.jsp пользователь вводит любую сумму и отправляет страницу. Отправленная сумма сохраняется в сеансе HTTP из-за

@ModelAttribute("goal") Goal goal

и

@SessionAttributes ( "цель" )

Без атрибута @ModelAttribute ( "цель" ), введенного пользователем на странице AddGoal, будет потеряно

Ответ 5

Я тоже борюсь с этим. Я прочитал этот пост, и он сделал несколько более ясных:

Установить переменную сеанса spring mvc 3

Насколько я понял, это в основном говорит:

  • что spring помещает объекты, указанные @SessionAttributes, в сеанс только для продолжительности между первым запросом GET и запросом POST, который приходит после него. После этого объект удаляется из сеанса. Я попробовал это в небольшом приложении и одобрил это выражение.

Итак, если вы хотите, чтобы объекты, которые длились дольше в течение нескольких запросов GET и POST, вам придется добавлять их вручную на HttpSession, как обычно.