2010-05-03 32 views
22

我在我的Spring控制器中設置了請求GET請求處理程序的表單對象。第一次用戶進入頁面時,應創建一個新的表單對象並設置爲請求。如果用戶發送表單,則從請求填充表單對象,現在表單對象具有所有用戶givern屬性。然後表單被驗證,如果驗證正確,則表單被保存到數據庫。如果表單未經驗證,我想將表單對象保存到會話中,然後重定向到GET請求處理頁面。當請求被重定向到GET處理程序時,它應該檢查會話是否包含表單對象。Spring Framework 3和會話屬性

我已經想通了,有@SessionAttributes(「形式」)在Spring註解,但由於某些原因下不工作,因爲在第一次會話屬性的形式爲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; 
} 

回答

24

@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可能會更清晰,在我看來。

+0

它幫助我,但是,如果第一次被調用,它會拋出異常。 – digz6666 2011-03-18 04:04:28

+0

@ digz6666,參見[#SPR-4452](https://jira.springsource.org/browse/SPR-4452) – 2011-09-07 12:20:17

+6

如果spring實現一個允許訪問會話屬性的方法參數註釋將很有用(在同樣你可以訪問請求參數)。 (@SessionAttribute(「貓」)貓貓){' – 2012-04-10 18:35:15

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 
    } 
} 
+12

+1,這是迄今爲止我見過的最好的解決方法,直到春天決定添加'@ModelAttribute(required = false)'。 – 2011-09-07 12:54:03

+0

感謝您的提示,這真的是開始頭痛 – nMoncho 2012-07-12 18:59:05

+0

是的,populateForm方法是我解決這個問題的關鍵。希望春天的文檔有點清晰:( – Jalpesh 2013-02-25 05:25:43

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

我與這個掙扎也是如此。我讀了這篇文章,並做了一些事情更清晰:

Set session variable spring mvc 3

據我的理解是這基本上是說:

  • 是春天提出由@SessionAttributes指定的對象到會話中僅第一個GET請求和POST請求之間的持續時間。之後,該對象將從會話中刪除。我在一個小應用程序中嘗試了它,並批准了該聲明。

因此,如果您想要在多個GET和POST請求中持續更長時間的對象,您必須像往常一樣手動將它們添加到HttpSession中。

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頁面上輸入量將會丟失