このバージョンはまだ開発中であり、まだ安定しているとは見なされていません。最新の安定バージョンについては、Spring Framework 7.0.9 を使用してください!

データバインド

データバインディングとは、文字列パラメーターを型変換を伴うオブジェクトグラフにバインドするメカニズムです。これは Spring Framework の中核となるメカニズムであり、アプリケーション構成に役立ちます。Web アプリケーションでは、文字列値のマップではなく、豊富な型を持つオブジェクトを介してクエリパラメーターやフォームデータに簡単にアクセスできるようになります。

データバインディングメカニズム(コンストラクターと setter のバインディング、プロパティ名の構文、型変換など)の詳細については、「コアテクノロジー」セクションのデータバインドを参照してください。

アノテーション付きコントローラーの場合、データバインディングは @ModelAttribute メソッドの引数に適用されます。関数エンドポイントの場合は、ServerRequest の bind メソッドを使用してください。

アノテーション付きコントローラーを使用するブラウザーアプリケーションの場合、@ModelAttribute メソッドを使用して、レンダリングされたビューで使用する追加のモデル属性を初期化できます。

各リクエストは個別の WebDataBinder インスタンスを使用します。アノテーション付きコントローラーの場合、このインスタンスはコントローラー内で @InitBinder メソッドを使用してカスタマイズするか、コントローラー間でコントローラーのアドバイスを使用してカスタマイズできます。関数エンドポイントの場合は、オーバーロードされた ServerRequest.bind メソッドを使用します。

モデル設計

データバインディングとは、信頼できない入力をアプリケーションオブジェクトにバインドすることです。セキュリティ上の理由から、入力が想定されるフィールドのみに適切に制限されていることを確認することが非常に重要です。このセクションでは、安全なバインディングのためのガイダンスを提供します。

まず、Web バインディングには不変オブジェクト設計を推奨します。コンストラクターによってバインディングが想定される入力に自然に制約されるため、安全です。Java レコードまたはプライマリコンストラクターを持つクラスを使用でき、どちらもさらにネストされたオブジェクトを持つことができます。詳細はコンストラクターのバインドを参照してください。

安全なバインディングを実現するもう一つの方法は、想定される入力に合わせて設計された専用オブジェクトを使用することです。このようなオブジェクトは、たとえ変更可能であっても、バインディングを想定される入力に限定するため安全です。

JPA エンティティや Hibernate エンティティなどのドメインオブジェクトは、想定される入力よりも多くのプロパティを含む可能性があるため、一般的に Web バインディングには適していません。このような場合、バインディング用に公開するプロパティを宣言することが重要です。例:

@Controller
public class PersonController {

	@InitBinder
	void initBinder(WebDataBinder binder) {
		// See Javadoc for supported pattern syntax
		binder.setAllowedFields("firstName", "lastName", "*Address");
	}
}
disallowedFields プロパティは、不安定で、時間の経過とともに実際のプロパティとの同期が崩れやすいため、Spring Framework 7.1 で非推奨 [GitHub] (英語) となりました。

allowedFields と disallowedFields に指定できるパターンは、トップレベルのフィールド名に限定されません。これらはプロパティパスであり、フレームワーク内の他の場所で Bean プロパティの読み書きに使用されている構文と同じ構文を使用します。また、ワイルドカードとして * もサポートしています。つまり、バインディングをより正確に制約できるということです。

  • "address" は address の特性と一致します。

  • "person.address.city" は、person のネストされた address プロパティの city プロパティと一致します。

  • "addresses[0].city" は、addresses 配列または List のインデックス 0 にある要素の city プロパティと一致します。

  • "map[key]" は、map プロパティ内の key に関連付けられたエントリと一致します。

  • "map*" は、"map[key1]" や "map[key2]" など、map プロパティのすべてのエントリに一致します。同じワイルドカード構文は、配列のインデックス付き要素または List にも適用されます。

サポートされているパターン構文の詳細については、DataBinder#setAllowedFields (Javadoc) の Javadoc を参照してください。

デフォルトでは、DataBinder はコンストラクターバインディングと setter バインディングの両方を適用します。これは不変オブジェクトと専用オブジェクトでは問題ありませんが、ドメインオブジェクトの場合は allowedFields を設定する必要があります。データバインディングが、期待される入力が明示的に宣言されている宣言スタイルでのみ使用されるようにするには、DataBinder に declarativeBinding を設定できます。これにより、コンストラクターバインディングが常に適用され、allowedFields が設定されている場合は条件付きで setter バインディングが適用されます。以下に、このフラグをグローバルに設定する方法を示します。また、ControllerAdvice の属性を使用して絞り込むこともできます。

@ControllerAdvice
public class ControllerConfig {

	@InitBinder
	void initBinder(WebDataBinder binder) {
		binder.setDeclarativeBinding(true);
	}
}