web-dev-qa-db-ja.com

Spring MVC:@RequestParamと@ModelAttributeの違いを説明してください

Spring MVCは初めてです。ドキュメントの開梱を手伝ってください。

ドキュメント

Spring MVC Documentation states(emphasis mine):

  • メソッド引数の@ModelAttributeは、モデルから引数を取得する必要があることを示します。モデルに存在しない場合は、引数を最初にインスタンス化してからモデルに追加する必要があります。モデルに表示されると、引数のフィールドは、一致する名前を持つすべてのリクエストパラメーターから入力されます。 WebDataBinderクラスは、要求パラメーター名と一致します-クエリ文字列パラメーターとフォームフィールドを含む———属性フィールドを名前でモデル化します。

  • @RequestParamは、リクエストパラメーターをコントローラーのメソッドパラメーターにバインドします。

免責事項/クラリファイヤー

@ModelAttribute@RequestParamは同じものではなく、相互に排他的ではなく、同じ役割を果たさず、同時に使用できることを知っています この質問 -実際、@RequestParamを使用して入力できます@ModelAttributeのフィールド。私の質問は、彼らの内部の働きの違いに向けられています。

質問:

@ModelAttribute(メソッドではなくメソッド引数で使用される)と@RequestParamの違いは何ですか?具体的には:

  • Source:@RequestParam@ModelAttributeの情報/母集団、つまりURLのリクエストパラメータは、フォームの要素として提供されている可能性がありますか/ POSTedされたモデル?
  • 使用法:@RequestParamで取得された変数は(モデルに渡されない限り)捨てられますが、@ModelAttributeで取得された変数はモデルに自動的に供給されますか?返される?

または、非常に基本的なコーディング例では、これら2つの例の実際の動作上の違いは何ですか?

例1:@RequestParam

// foo and bar are thrown away, and are just used (e.g.) to control flow?
@RequestMapping(method = RequestMethod.POST)
public String testFooBar(@RequestParam("foo") String foo,
@RequestParam("bar") String bar, ModelMap model) {
    try {
     doStuff(foo, bar);
    }
    // other code
  }

例2:@ModelAttribute

// FOOBAR CLASS
// Fields could of course be explicitly populated from parameters by @RequestParam
public class FooBar{
    private String foo;
    private String bar;
   // plus set() and get() methods
}

// CONTROLLER
// Foo and Bar become part of the model to be returned for the next view?
@RequestMapping(method = RequestMethod.POST)
public String setupForm(@ModelAttribute("fooBar") FooBar foobar) {
   String foo = fooBar.getFoo();
   String bar = fooBar.getBar();
   try {
      doStuff(foo, bar);
   }
   // other code
}

私の現在の理解:

@ModelAttribute@RequestParamは両方とも、要求パラメーターに情報を問い合わせますが、この情報の使い方は異なります。

  • @RequestParamは、スタンドアロン変数(もちろん、@ModelAttributeクラスのフィールド)を設定するだけです。これらの変数は、モデルに入力されていない限り、コントローラーが完了すると破棄されます。

  • @ModelAttributeは、クラスのフィールドにデータを設定します。これにより、モデルの属性が設定され、ビューに戻されます

これは正しいです?

46
Lydia Ralph

_@RequestParam_は、スタンドアロン変数(もちろん、_@ModelAttribute_クラスのフィールドである可能性があります)を設定するだけです。これらの変数は、モデルに入力されていない限り、コントローラーが完了すると破棄されます。

Wordの「モデル」とセッションを混同しないでください。 httpの会話は通常、_HTTP.GET_、サーバー応答、そして__HTTP.POST_です。 _@ModelAttribute_注釈を使用している場合、注釈を付けたもののインスタンスを常に構築しているので、「モデルに物を与える」ことで変数が固定される可能性があると思われます。 HttpServletRequestが終了すると、これらの変数はセッションに保存されない限り、ブラウザー/サーバーの会話の一部ではなくなります。これは正しくありません。

_@ModelAttribute_は、クラスのフィールドにデータを設定し、ビューに返されるモデルの属性を設定します

はい!正確に言うと、_@ModelAttribute_は、デフォルトのWebデータバインダーを使用してHttpServletRequestからのデータをインスタンスに入力するようにSpringに指示します。このデータをビューに戻すことを選択するのはプログラマー次第です。 _@ModelAttribute_アノテーションが付けられたメソッドがある場合、コードがそのサーブレットにヒットするたびに呼び出されます。メソッドのパラメーターの1つとして_@ModelAttribute_がある場合、着信Httpフォームのデータバインディングについて説明しています。

_@RequestParam_を呼び出すことは、request.getParameter("foo");を言うためのショートカットです。内部では、JavaのHttpServletRequestを使用すると、キーから値へのルックアップを実行して、リクエストオブジェクトから値を取得できます。返される値はObject型です。これは、WebアプリケーションでSpringを使用していない場合によく入力するものです。

_@ModelAttribute_の使用を開始すると、Springはこの抽象化をさらに一歩進めます。この注釈は、データバインディングの概念を採用しています。データバインディングの目標は、コントローラーのコードがすべてのフォーム要素に対してrequest.getParameter("foo1")を呼び出す必要がないことです。 5つのフィールドを持つWebフォームがあるとします。データバインドを使用しない場合、プログラマはこれらの各フィールドを手動で取得して検証する必要があります。プログラマーは、リクエストにプロパティが含まれていること、プロパティの値が存在すること、およびプロパティの値が各フィールドに期待されるタイプであることを確認する必要があります。 _@ModelAttribute_を使用すると、Springにこの作業を行うように指示されます。

コントローラーのメソッドに@ModelAttribute("fooBar") FooBar fooBarアノテーションを付ける場合、FooBarのインスタンスは、Springによってalwaysに構築され、メソッドに提供されます。データバインディングが機能するのは、このアノテーションがメソッドのパラメーターで使用されるときです。 SpringはHttpServletRequestのインスタンスを調べ、FooBarのインスタンスの適切なプロパティへのリクエストのデータと一致するかどうかを確認します。これはJavaプロパティの慣習に基づいています。ここでは、fooなどのフィールドと、getFooおよびsetFooという名前のパブリックgetterおよびsetterがあります。これは魔法のように思えるかもしれませんが、慣習に違反すると、SpringデータバインディングはHttpServletRequestからのデータをバインドするためにwhereを知ることができないため、動作を停止します。は引き続きFooBarのインスタンスを取得しますが、プロパティはリクエストからの値に設定されません。

40
zmf

@ModelAttribute:Javaオブジェクト(Employeeなど)全体をバインドします。複数の要求パラメーターをサポートします。

@RequestParam:単一の要求パラメーター(firstNameなど)をバインドします

一般に、
@RequestParamは、少数のパラメーターを読み取るのに最適です。

@ModelAttributeは、多数のフィールドを持つフォームがある場合に使用されます。

そして

@ModelAttributeは、データバインディング、検証、フォームの事前入力などの追加機能を提供します。

6
Harinath

@ModelAttribute注釈付きパラメーターは登録済みServletModelAttributeMethodProcessor(またはModelAttributeMethodProcessor)によって処理され、@RequestParam注釈付きパラメーターは登録済みRequestParamMethodArgumentResolverまたはRequestParamMapMethodArgumentResolverによって処理されますパラメータタイプ。

ここでは、SpringがこれらのHandlerMethodArgumentResolversを使用してハンドラーメソッドの引数を解決する方法について説明します。

両方の場合、@ModelAttributeおよび@RequestParamの場合、バインドされる値は ServletRequest parameters から取得されます。

上記のタイプのソースコードを見ることができますが、簡単な詳細を以下に示します。

@ModelAttributeの場合、Springはパラメータータイプのインスタンスを作成します。そのインスタンスのフィールドを検査し、@ModelAttribute名とフィールド名で構成される命名/エイリアス戦略に基づいてパラメーター値をそれらにバインドしようとします。通常、Converterインスタンスのグループを使用して、String(パラメーター値は常に​​String値)からターゲットフィールドタイプIntegerDate、独自のConverter型をカスタム変換用に登録することもできます。 POJO型をネストすることもできます。

@RequestParamの場合、Springは同じConverterインスタンスを使用して、パラメーター値から注釈付きパラメータータイプに直接変換します。

パラメーター値は「破棄」されないことに注意してください。それらは、コンテナのリクエスト処理サイクルの間、HttpServletRequestに保存されます。 適切なメソッド でいつでもアクセスできます。

@ModelAttribute(parameter)は、@SessionAttributesまたは@ModelAttribute(method)からモデル属性をロードします。

リクエストの値をバインドするためだけに必要ではありませんが、@SessionAttributesからロードした後にバインドします。

@RequestParamは、リクエストパラメータをオブジェクトにバインドします。

0
Neil McGuigan