Когда удаляются @SessionAttributes в SpringMVC? (С образцом кода)

В каких точных условиях очищаются @SessionAttributes? Я обнаружил какое-то запутанное поведение при попытке использовать две модели на странице.

Когда я делаю GET, а затем POST с помощью этого контроллера...

@Controller
@RequestMapping("/myPage*")
@SessionAttributes(value = {"object1", "object2"})
public class MyController {

  @RequestMapping(method = RequestMethod.GET)
  public String get(Model model) {
      model.addAttribute("object1", new Object1());
      model.addAttribute("object2", new Object2());
      return "myPage";
  }

  @RequestMapping(method = RequestMethod.POST)
  public String post(@ModelAttribute(value = "object1") Object1 object1) {
      //do something with object1
      return "myPage";
  }
}

... object2 очищается от модели. Он больше не существует как @SessionAttribute и не может быть доступен на моей странице просмотра.

Однако, если подпись второго метода изменена на это...

public String post(@ModelAttribute(value = "object1") Object1 object1,
                   @ModelAttribute(value = "object2") Object2 object2) {

... тогда object2 не очищается от модели и доступен на моей странице просмотра.

В javadoc для @SessionAttributes говорится:

... атрибуты будут удалены один раз обработчик указывает на завершение его разговорную сессию.

Но я не вижу, как я указал завершение сеанса общения в первом примере, но не во втором примере.

Может кто-нибудь объяснить это поведение или это ошибка?

Ответы

Ответ 1

Вы указываете завершение разговора, вызывая

SessionStatus.setComplete

public void post(...., SessionStatus status) {
  status.setComplete();
}

Тем не менее, я не понимаю, почему вы должны потерять один атрибут модели, а не другой.

Вы пытались сделать что-то вроде:

@ModelAttribute("object1")
public Object object1() { return new Object(); }

@ModelAttribute("object2")
public Object object2() { return new Object(); }

И посмотрите, как это сравнивается с помещением атрибутов в модель вручную.

Ответ 2

Вы можете удалить один и тот же тип ModelAttribute для сеанса следующим образом:

Учитывая ModelMap model, HttpSession session, и вы делаете:

if (categoryId != null) 
    model.addAttribute("categoryId", categoryId);
else {
    model.remove("categoryId");
    session.removeAttribute("categoryId");
}