2010-05-03 53 views
22

Tôi có đối tượng biểu mẫu mà tôi đã đặt để yêu cầu trong trình xử lý yêu cầu GET trong bộ điều khiển Spring của tôi. Lần đầu tiên người dùng nhập vào trang, một đối tượng biểu mẫu mới sẽ được thực hiện và thiết lập để yêu cầu. Nếu người dùng gửi biểu mẫu, thì đối tượng biểu mẫu được điền từ yêu cầu và bây giờ đối tượng biểu mẫu có tất cả các thuộc tính của người dùng. Sau đó, biểu mẫu được xác thực và nếu xác thực là ok, thì biểu mẫu được lưu vào cơ sở dữ liệu. Nếu biểu mẫu không được xác nhận, tôi muốn lưu đối tượng biểu mẫu vào phiên và sau đó chuyển hướng đến trang xử lý yêu cầu GET. Khi yêu cầu được chuyển hướng đến trình xử lý GET, thì nó sẽ kiểm tra xem phiên có chứa đối tượng biểu mẫu hay không.Spring Framework 3 và thuộc tính phiên

tôi đã tìm ra rằng có @SessionAttributes ("hình thức") chú thích trong mùa xuân, nhưng đối với một số lý do sau doesnt làm việc, bởi vì lúc đầu tiên, hình thức thuộc tính phiên là null và nó mang lại cho lỗi:

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

đây là bộ điều khiển của tôi:

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

Trả lời

24

công việc của @SessionAttribute là để ràng buộc một đối tượng mô hình hiện có để phiên. Nếu nó chưa tồn tại, bạn cần phải xác định nó. Đó là không cần thiết gây nhầm lẫn, theo ý kiến ​​của tôi, nhưng thử một cái gì đó như thế này:

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

Lưu ý rằng @SessionAttributes được khai báo trên lớp, chứ không phải là phương pháp. Bạn có thể đặt bất cứ nơi nào bạn thích, thực sự, nhưng tôi nghĩ rằng nó có ý nghĩa hơn về lớp học.

The documentation on this có thể rõ ràng hơn nhiều, theo ý kiến ​​của tôi.

+0

Nó đã giúp tôi nhưng, ngoại lệ ném của nó nếu được gọi là lần đầu tiên. – digz6666

+0

@ digz6666, xem [# SPR-4452] (https://jira.springsource.org/browse/SPR-4452) –

+6

Sẽ hữu ích nếu mùa xuân đã triển khai chú thích tham số phương thức cho phép truy cập vào thuộc tính phiên (trong giống như cách bạn có thể truy cập thông số yêu cầu). 'public void doSometing (@SessionAttribute (" cat ") Cat cat) {' –

32

Nó ném ngoại lệ nếu bộ điều khiển được gọi là lần đầu tiên mặc dù đã thêm @SessionAttributes ({"form"}) vào lớp. Vì vậy, thêm phương thức populateForm sau đây sẽ sửa lỗi này.

@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, đây là giải pháp tốt nhất mà tôi đã thấy cho đến giờ, cho đến khi mùa xuân quyết định thêm '@ModelAttribute (required = false)'. –

+0

Cảm ơn gợi ý, Nó đã thực sự bắt đầu là một nhức đầu – nMoncho

+0

Vâng, phương pháp populateForm là chìa khóa cho tôi trong việc giải quyết này. Chúc tài liệu mùa xuân là một chút rõ ràng hơn: ( – Jalpesh

1

nếu không có đối tượng session được xác định vì vậy tôi nghĩ rằng nó sẽ là như thế này:

@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

Tôi đang phải vật lộn với điều này là tốt. Tôi đọc bài này và nó thực hiện một số điều rõ ràng hơn:

Set session variable spring mvc 3

Theo như tôi hiểu nó này về cơ bản nói:

  • rằng mùa xuân đặt đối tượng theo quy định của @SessionAttributes vào phiên này chỉ dành cho khoảng thời gian giữa yêu cầu GET đầu tiên và yêu cầu POST xuất hiện sau yêu cầu đó. Sau đó đối tượng được loại bỏ khỏi phiên. Tôi đã thử nó trong một ứng dụng nhỏ và nó đã thông qua tuyên bố.

Vì vậy, nếu bạn muốn có đối tượng kéo dài hơn trong nhiều yêu cầu GET và POST, bạn sẽ phải thêm chúng theo cách thủ công vào HttpSession, như thường lệ.

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"; 
    } 
} 

Trên trang thêm người dùngGoal.jsp nhập số tiền bất kỳ và gửi trang.lượng văn được lưu trữ trong HTTP phiên vì

@ModelAttribute("goal") Goal goal 

@SessionAttributes ("Mục tiêu")

Without @ModelAttribute ("Mục tiêu") lượng nhập vào bởi người dùng trên trang addGoal sẽ bị mất

Các vấn đề liên quan