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
作成されたどこを?誰が私たちのためにそれを作成しているので、もし?
モデル内に存在しない場合は、引数が最初にインスタンス化し、そのモデルに追加する必要があります。
段落は、次のコードを説明します。
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
製モデルとビュー関連の決定を記録インスタンスHandlerMethodArgumentResolver
Sと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
必ずすべてのフィールドを作成するpetId
とownerId
、正しくバインドされていたが。
Pet[456,123,XXX]
私たちは、設定されhiddenField
私たちの理論をチェックすると、メソッドにリダイレクトinvokeInternal
も期待し@ModelAttribute
。我々が見るように、第二の方法は、第一の方法のために作成した(自分の隠された値で)インスタンスを受けました。