場所を正確に春のMVCで作成したモデルオブジェクトのですか?

JAVA:

docs.spring.org参照からいくつかのチュートリアルと初期の原稿の読み取りを通過した後、私はそれが開発者によって作成されたPOJOクラスのコントローラで作成されていることがわかります。これを読みながら、しかし、私は段落の下に出くわしました:

@ModelAttributeメソッドの引数には、引数がモデルから取得されるべきであることを示します。モデル内に存在しない場合は、引数が最初にインスタンス化し、そのモデルに追加する必要があります。モデル内に存在すると、引数のフィールドは、一致する名前を持つすべてのリクエストパラメータから移入されなければなりません。これは、Spring MVCの、個別に各フォームフィールドを解析する必要がなくなります非常に便利な機構では、データ・バインディングとして知られています。

@RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
public String processSubmit(@ModelAttribute Pet pet) {

}

春のドキュメント

最も邪魔されているものの段落での行は次のようになります。

「モデルに存在しない場合は...」

どのようにデータがモデルであっすることができますか?(私たちがモデルを作成していないので - それは私達によって作成されます。)

また、私は受け入れて、いくつかのコントローラメソッド見てきたModel引数としてタイプを。どういう意味ですか?それが取得されてModel作成されたどこを?誰が私たちのためにそれを作成しているので、もし?

アンドリューTobilko:

モデル内に存在しない場合は、引数が最初にインスタンス化し、そのモデルに追加する必要があります。

段落は、次のコードを説明します。

if (mavContainer.containsAttribute(name)) {
    attribute = mavContainer.getModel().get(name);
} else {
    // Create attribute instance
    try {
        attribute = createAttribute(name, parameter, binderFactory, webRequest);
    }
    catch (BindException ex) {
        ...
    }
}
...
mavContainer.addAllAttributes(attribute);

(から採取ModelAttributeMethodProcessor#resolveArgument

すべての要求のために、スプリングは初期化ModelAndViewContainer製モデルとビュー関連の決定を記録インスタンスHandlerMethodArgumentResolverSとHandlerMethodReturnValueHandlerコントローラメソッドの呼び出しの過程で秒。

新しく作成されModelAndViewContainerたオブジェクトは、最初に移入されたフラッシュの属性(もしあれば):

ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));

それはすでにモデル内に存在する場合、引数は初期化されないことを意味します。

それを証明するために、のは、実用的な例に移りましょう。

Petクラス:

public class Pet {
    private String petId;
    private String ownerId;
    private String hiddenField;

    public Pet() {
         System.out.println("A new Pet instance was created!");
    }

    // setters and toString
}

PetControllerクラス:

@RestController
public class PetController {

    @GetMapping(value = "/internal")
    public void invokeInternal(@ModelAttribute Pet pet) {
        System.out.println(pet);
    }

    @PostMapping(value = "/owners/{ownerId}/pets/{petId}/edit")
    public RedirectView editPet(@ModelAttribute Pet pet, RedirectAttributes attributes) {
        System.out.println(pet);
        pet.setHiddenField("XXX");

        attributes.addFlashAttribute("pet", pet);
        return new RedirectView("/internal");
    }

}

のは、URIにPOSTリクエストを作ろう/owners/123/pets/456/editとの結果を参照してください。

A new Pet instance was created!
Pet[456,123,null]
Pet[456,123,XXX]

A new Pet instance was created!

春は作成ModelAndViewContainerして使用してインスタンスを埋めるために何かを見つけることができませんでした(;任意のリダイレクトはありませんでしたそれは、クライアントからのリクエストです)。モデルが空なので、春は新しい作成する必要がありましたPetラインを印刷し、既定のコンストラクタを呼び出すことによって、オブジェクトを。

Pet[456,123,null]

モデル内に存在すると、引数のフィールドは、一致する名前を持つすべてのリクエストパラメータから移入されなければなりません。

私たちは、与えられた印刷Pet必ずすべてのフィールドを作成するpetIdownerId、正しくバインドされていたが。

Pet[456,123,XXX]

私たちは、設定されhiddenField私たちの理論をチェックすると、メソッドにリダイレクトinvokeInternalも期待し@ModelAttribute我々が見るように、第二の方法は、第一の方法のために作成した(自分の隠された値で)インスタンスを受けました。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=175845&siteId=1