この場合、@ModelAttribute
注釈は、Springがモデル属性として追加する必要のあるオブジェクトを識別するために使用されます。モデル属性は、HttpServletRequest
属性の抽象です。基本的には、属性はHttpServletRequest
の属性に変換されるいくつかのキーによって識別されるオブジェクトです。これを行うには、Model#addAttribute(String, Object)
という属性を手動で追加するか、@ModelAttribute
注釈付きの方法を使用するか、または@ModelAttribute
というメソッドパラメーターに注釈を付けることによってこれを行うことができます。
Springはハンドラメソッドのパラメータを解決して引数を挿入する方法を理解する必要があります。これは、HandlerMethodArgumentResolver
インターフェイスを使用して行います。いくつかの実装クラス(javadocを参照)があり、それぞれがresolveArgument()
への責任を持ちます。これは、Springがリフレクションを通してハンドラメソッドinvoke()
に使用する引数を返します。SpringはHandlerMethodArgumentResolver
supportsParameter()
メソッドが特定のパラメータに対してtrue
を返す場合にのみ、resolveArgument()
メソッドを呼び出します。ここで問題になっている
HandlerMethodArgumentResolver
実装は
@ModelAttributeでアノテーション付きメソッドの引数を解決し、@ModelAttributeで注釈が付け方法から の戻り値の処理を述べたModelAttributeMethodProcessor
から延びているServletModelAttributeMethodProcessor
です。
春(3.2)春は、あなたのハンドラメソッドを呼び出すために必要がある場合registerこのHandlerMethodArgumentResolver
など
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
// Annotation-based argument resolution
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
// Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters()));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
// Custom arguments
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
// Catch-all
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
resolvers.add(new ServletModelAttributeMethodProcessor(true));
return resolvers;
}
、それはパラメータの型を通って、上記のリストを反復処理し、最初のものを使用しますしますそのsupportsParameter()
。
ServletModelAttributeMethodProcessor
という2つのインスタンスが追加されています(//catch all
コメントの後に1つ)。 ModelAttributeMethodProcessor
にはannotationNotRequired
フィールドがあり、それは@ModelAttribute
を探すべきかどうかを示します。最初のインスタンスは@ModelAttribute
を検索する必要があり、2番目のインスタンスは検索しません。 Springは独自のHandlerMethodArgumentResolver
インスタンスを登録できるようにこれを行います。// Custom arguments
のコメントを参照してください。この場合
具体的
@RequestMapping(value = "/", method = RequestMethod.POST)
public String sayHello(Person person, Model model) {
model.addAttribute("person", person);
return "home";
}
あなたPerson
パラメータが注釈されているかどうか、それは問題ではありません。 ModelAttributeMethodProcessor
はそれを解決し、フォームフィールドをバインドします。要求パラメータをインスタンスのフィールドに追加します。 ModelAttributeMethodProcessor
クラスがそれを処理するので、model
に追加する必要はありません。あなたのshowHelloPage()
方法
model.addAttribute("person", new Person());
で
は<form>
のtaglibで必要とされています。それがそのフィールドのinput
を解決する方法です。
だから私の質問はある - "ModelAttribute" anonnatationの使用は何ですか?
モデルに指定されたパラメータ(またはメソッドの戻り値)を自動的に追加します。
フォームの「modelAttribute」属性を省略する方法はありますか?
いいえ、Model
内のオブジェクトのためのform
結合ルックスとinput
要素をHTMLにそのフィールドをバインドします。
第2の部分は、自動的に フォームを作る(メソッドのパラメータとして宣言されます)適切なBeanのプロパティ への入力の値をバインドする方法(おそらくいくつかの注釈)は何ですか?フォームを送信する前に空のBeanを に追加する必要はありません(今のように)。
スプリング<form>
タグは、モデル属性オブジェクトにラッチしinput
とlabel
要素を作成するために、そのフィールドを使用します。オブジェクトがモデル内でどのように終わったかは問題ではありません。指定した名前(キー)のモデル属性が見つからない場合は、見たように例外がスローされます。
<form:form method="post" modelAttribute="person">
空のBeanを提供する代わりに、自分でhtmlを作成することができます。すべてのSpringの<form>
は、Beanのフィールド名を使用してinput
要素を作成します。したがって、この
<form:form method="post" modelAttribute="person">
<form:label path="firstName">First name</form:label>
<form:input path="firstName" />
は
<form method="post" action="[some action url]">
<label for="firstName">First name<label>
<input type="text" name="firstName" value="[whatever value firstName field had]" />
...
春のようなものがname
属性を使用して、インスタンスフィールドにリクエストパラメータをバインドし作成します。
ご返信いただきありがとうございます、あなたは私に多くの説明をしました。 "ModelAttribute"アノテーションに関するもう1つの質問 - 私が正しく理解している場合、メソッドのパラメータで使用されるこのアノテーションは "model.addAttribute(...)"と同等ですか? –
@MichałTaborメソッドパラメータとして追加してみてください。要求にバインド可能なリクエストパラメータがないため、nullが返される場合は不明です。それ以外の場合、あなたがやっているやり方は正しい方法です。これらは、データ転送オブジェクト(またはSpringフォームのバッキングオブジェクト/コマンドオブジェクト)として知られています。ドキュメントには詳細が必要です。 –
+1、すばらしい説明 – rocketboy