この場合の@ModelAttribute
アノテーションは、Spring がモデル属性として追加する必要があるオブジェクトを識別するために使用されます。モデル属性は、属性からの抽象化HttpServletRequest
です。基本的に、それらは、HttpServletRequest
属性への道を見つけるいくつかのキーによって識別されるオブジェクトです。これを行うには、属性を手動で追加するかModel#addAttribute(String, Object)
、@ModelAttribute
注釈付きのメソッドを用意するか、メソッド パラメータに を使用して注釈を付けます@ModelAttribute
。
理解する必要があるのは、Spring がハンドラー メソッドのパラメーターを解決し、引数を挿入する方法です。HandlerMethodArgumentResolver
そのためにインターフェイスを使用します。多数の実装クラスがあり (javadoc を参照)、 Spring が使用する引数をリフレクションを通じてハンドラー メソッドresolveArgument()
に返す責任があります。invoke()
Spring は、メソッドが特定のパラメーターに対して返されたresolveArgument()
場合にのみメソッドを呼び出します。HandlerMethodArgumentResolver
supportsParameter()
true
ここHandlerMethodArgumentResolver
で問題となっている実装は、どの状態ServletModelAttributeMethodProcessor
から拡張されているかです。ModelAttributeMethodProcessor
@ModelAttribute アノテーションが付けられたメソッド引数を解決し、@ModelAttribute アノテーションが付けられたメソッドからの戻り値を処理します。
Spring (3.2) はこれと他のものを登録します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;
}
Spring がハンドラー メソッドを呼び出す必要がある場合、Spring はパラメーターの型と上記のリストを反復処理し、supportsParameter()
.
の 2 つのインスタンスServletModelAttributeMethodProcessor
が追加されていることに注意してください (//catch all
コメントの後に 1 つ)。には、を探すかどうかをModelAttributeMethodProcessor
示すフィールドがあります。最初のインスタンスは を探す必要がありますが、2 番目のインスタンスは探しません。Spring はこれを行うため、独自のインスタンスを登録できます。コメントを参照してください。annotationNotRequired
@ModelAttribute
@ModelAttribute
HandlerMethodArgumentResolver
// Custom arguments
具体的には
@RequestMapping(value = "/", method = RequestMethod.POST)
public String sayHello(Person person, Model model) {
model.addAttribute("person", person);
return "home";
}
この場合、Person
パラメーターに注釈が付けられているかどうかは問題ではありません。AModelAttributeMethodProcessor
はそれを解決し、フォーム フィールドをバインドします。リクエスト パラメータをインスタンスのフィールドに追加します。クラスがそれを処理するmodel
ため、に追加する必要さえありません。ModelAttributeMethodProcessor
あなたのshowHelloPage()
方法では
model.addAttribute("person", new Person());
<form>
taglibで必要です。それがinput
フィールドを解決する方法です。
だから私の質問は - 「ModelAttribute」注釈の使用は何ですか?
指定されたパラメーター (またはメソッドの戻り値) をモデルに自動的に追加します。
フォームで「modelAttribute」属性を省略する方法はありますか?
いいえ、form
バインディングは 内のオブジェクトを探し、Model
そのフィールドを htmlinput
要素にバインドします。
そして2番目の部分、フォームが入力の値を適切なBeanのプロパティ(メソッドパラメータとして宣言される)に自動的にバインドする方法(おそらく何らかの注釈)は何ですか?フォームを送信する前に空の Bean を追加する必要はありません (今はそうしなければなりません)。
Spring<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
Spring は、属性を使用してリクエスト パラメータをインスタンス フィールドにバインドします。