Spring Framework 3和会话属性

时间:2010-05-03 09:43:41

标签: session spring-mvc

我有我在Spring控制器中的GET请求处理程序中请求的表单对象。第一次用户进入页面时,应该创建一个新的表单对象并设置为request。如果用户发送表单,则表单对象将从请求中填充,现在表单对象具有所有用户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;
}

5 个答案:

答案 0 :(得分:32)

如果控制器第一次调用,即使将@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
   }
}

答案 1 :(得分:25)

@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是在类上声明的,而不是方法。你可以把它放在任何你喜欢的地方,但我觉得它在课堂上更有意义。

在我看来,

The documentation on this可能会更加清晰。

答案 2 :(得分:1)

如果没有已定义的会话对象,那么我认为它会是这样的:

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

答案 3 :(得分:1)

@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页面上输入的金额将会丢失

答案 4 :(得分:0)

我也在努力解决这个问题。我读了这篇文章,它让事情变得更加清晰:

Set session variable spring mvc 3

据我了解,这基本上说:

  • Spring将@SessionAttributes指定的对象放入会话中仅持续第一个GET请求和后面的POST请求之间的持续时间。之后,该对象将从会话中删除。我在一个小应用程序中尝试了它并批准了该声明。

因此,如果您希望在多个GET和POST请求中拥有持续时间较长的对象,则必须像往常一样手动将它们添加到HttpSession中。