在Portlet Spring MVC中不再调用@ModelAttribute方法

时间:2012-11-30 21:03:14

标签: spring-mvc liferay portlet

我的问题可以归结为:如何让spring mvc在已经填充后调用@ModelAttribute

详细说明,我正在使用 Portlets in Action 中的第8章中的BookCatalog示例 由Ashish Sarin(这真的很好),我遇到了一个注释方法的问题 @ModelAttribute仅在连续加载时才被调用一次。例如:

  1. 显示BookCatalog Portlet
  2. 点击编辑Book1。 Book1以编辑形式显示
  3. 点击主页
  4. 点击编辑Book2。 Book1 仍然显示在编辑表单中
  5. 我已经将sysouts添加到每个方法的开头,以查看所调用的内容。结果如下:

    showBooks 
    getBook!
    initBinder
    showEditBookForm
    showBooks
    initBinder <- Where is getBook!?
    showEditBookForm
    

    我在某处读到@ModelAttribute只要@ModelAttribute调用@ModelAttribute("book") Book book方法 请求参数。所以我尝试将@ModelAttribute添加到showEditBookForm但仍然没有触发@Controller @RequestMapping(value="VIEW") @SessionAttributes({"book"}) public class EditBookController { ... @RenderMapping(params="myaction=editBookForm") public String showEditBookForm(@ModelAttribute("book") Book book) { System.out.println("showEditBookForm"); return "editBookForm" } @InitBinder("book") public void initBinder(WebDataBinder binder) { System.out.println("initBinder"); binder.registerCustomEditor(Long.class, new LongNumberPropertyEditor()); binder.setDisallowedFields(new String[] {"isbnNumber"}); } @ModelAttribute("book") public Book getBook(@RequestParam Long isbnNumber) { System.out.println("getBook!"); return bookService.getBook(isbnNumber); } ... } 方法。

    我正在使用Spring 3.1.3.RELEASE并使用maven部署到Liferay 6.1.1。

    任何帮助都将不胜感激!

    EditBookController:

    @Controller
    @RequestMapping(value = "VIEW")
    public class BookController {
        ...
        @RenderMapping
        public String showBooks(RenderResponse response,SessionStatus sessionStatus) {
           System.out.println("showBooks");
           return "home";
        }
        ...
    }
    

    BookController的:

    {{1}}

2 个答案:

答案 0 :(得分:3)

根据这行代码:

@SessionAttributes({"book"})
public class EditBookController {

您正在使用“book”属性作为会话属性。这意味着第一次向Portal发出请求时,框架将验证Portlet会话中是否存在具有该名称的属性。如果不是,它将调用相应的@ModelAttribute方法生成实例并将其放入Session。但是如果Session中已经存在具有该名称的属性,则Controller将使用现有对象。

因此,当您第一次调用Book Catalog Portlet时,会生成Book属性的一个实例并将其存储在Session中。但第二次 - 如果一个对象已经在Session中 - Portlet将使用第一个请求中生成的对象。如果要在渲染或操作请求后清除存储在Session中的每个对象,只需调用SessionStatus.setComplete()即可触发会话清理。

这就是理论和书中所说的,但SessionStatus.setComplete()Book Author has some thoghts about it中存在一些错误的行为。

答案 1 :(得分:0)

只是为了说明我最终的目标:

@RenderMapping(params="myaction=editBookForm")
public String showEditBookForm(
        @ModelAttribute("book") Book book
        , @RequestParam Long isbnNumber
        , SessionStatus sessionStatus) {
        System.out.println("showEditBookForm");

       if(book != null 
          && book.getIsbnNumber() != isbnNumber) {
           sessionStatus.setComplete();
       }

       return "editBookForm";
}