2

私の質問は要約すると、Spring MVC@ModelAttributeがすでに入力された後、どのように呼び出すようにしますか?

詳述すると、私はアシシュ・サリンによるPortlets in Actionの第8章のBookCatalogの例をいじって います(これは本当に良いです)。そして、注釈が付けられたメソッド @ModelAttributeが連続したロードでも一度だけ呼び出されるという問題に遭遇しました。例えば:

  1. BookCatalogポートレットが表示されます
  2. [ブックの編集1]をクリックします。Book1が編集フォームに表示されます
  3. ホームをクリック
  4. [Book2の編集]をクリックします。Book1は引き続き編集フォームに表示されます

各メソッドの先頭にsysoutを追加して、何がどこで呼び出されているかを確認しました。結果は次のとおりです。

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

パラメータが要求さ@ModelAttributeれるたびにメソッドが呼び出されることをどこかで読みました。@ModelAttributeそこで@ModelAttribute("book") Book book、showEditBookFormに追加しようとしましたが、それでもメソッドがトリガーされないようです@ModelAttribute

Spring 3.1.3.RELEASEを使用しており、Mavenを使用してLiferay6.1.1にデプロイしています。

どんな援助もいただければ幸いです!

EditBookController:

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

    ...
}

BookController:

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

2 に答える 2

3

このコード行によると:

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

「book」属性をセッション属性として使用しています。これは、ポータルに対して初めてリクエストが行われたときに、フレームワークがその名前の属性がポートレットセッションに存在することを確認することを意味します。そうでない場合は、対応するメソッドを呼び出して@ModelAttributeインスタンスを生成し、Sessionに配置します。ただし、Sessionにその名前の属性がすでに存在する場合、コントローラーは既存のオブジェクトを使用します。

したがって、ブックカタログポートレットを初めて呼び出すと、ブック属性のインスタンスが生成され、セッションに保存されます。ただし、2回目は、オブジェクトがすでにセッションにあるため、ポートレットは最初の要求で生成されたオブジェクトを使用します。レンダリングまたはアクション要求の後にSessionに格納されているすべてのオブジェクトをクリアする場合はSessionStatus.setComplete()、セッションのクリーンアップをトリガーするために呼び出す必要があります。

それは理論と本が言ったことですが、中にはバグのある振る舞いがSessionStatus.setComplete()あり、本の著者はそれについていくつかの考えを持っています。

于 2012-12-01T01:19:17.447 に答える
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";
}
于 2012-12-03T15:50:48.113 に答える