Session Spring框架3和会话属性

Session Spring框架3和会话属性,session,spring-mvc,Session,Spring Mvc,我在Spring控制器中的GET请求处理程序中将表单对象设置为请求。用户第一次进入页面时,应创建一个新的表单对象并将其设置为请求。若用户发送表单,那个么表单对象将从请求中填充,现在表单对象具有所有用户给定的属性。然后对表单进行验证,若验证正常,则表单保存到数据库中。若表单未经验证,我想将表单对象保存到会话,然后重定向到“获取请求处理”页面。当请求被重定向到GET处理程序时,它应该检查会话是否包含表单对象 我发现Spring中有@SessionAttributes(“form”)注释,但由于某些原

我在Spring控制器中的GET请求处理程序中将表单对象设置为请求。用户第一次进入页面时,应创建一个新的表单对象并将其设置为请求。若用户发送表单,那个么表单对象将从请求中填充,现在表单对象具有所有用户给定的属性。然后对表单进行验证,若验证正常,则表单保存到数据库中。若表单未经验证,我想将表单对象保存到会话,然后重定向到“获取请求处理”页面。当请求被重定向到GET处理程序时,它应该检查会话是否包含表单对象

我发现Spring中有@SessionAttributes(“form”)注释,但由于某些原因,下面的注释不起作用,因为第一次,会话属性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;
}

@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({"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
   }
}
请注意,
@SessionAttributes
是在类上声明的,而不是在方法上声明的。你可以放在任何你喜欢的地方,真的,但我认为这在课堂上更有意义


在我看来,这可能更清楚。

若控制器第一次调用,即使在类中添加了@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
   }
}

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

@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({"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
   }
}

我也在努力解决这个问题。我读了这篇文章,它让一些事情更清楚了:

据我所知,这基本上是说:

  • Spring将@SessionAttributes指定的对象仅在第一个GET请求和之后的POST请求之间的时间段内放入会话。之后,对象将从会话中移除。我在一个小应用程序中尝试了它,它批准了该声明
因此,如果您希望在多个GET和POST请求中拥有持续时间更长的对象,则必须像往常一样手动将它们添加到HttpSession中

@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

@会期贡献(“目标”)


如果没有@modeldattribute(“goal”),用户在addGoal页面上输入的数量将丢失

这对我很有帮助,但如果第一次调用时抛出异常。如果spring实现允许访问会话属性的方法参数注释(与访问请求参数的方式相同),这将非常有用<代码>公共无效剂量测量(@SessionAttribute(“cat”)cat cat){+1,这是迄今为止我见过的最好的解决方法,直到spring决定添加
@ModelAttribute(required=false)
。谢谢你的提示,这真的开始让人头疼了。populateForm方法是我解决这个问题的关键。希望spring文档更清晰一点:(