Spring Data REST レスポンスハンドラーのオーバーライド
場合によっては、特定のリソースのカスタムハンドラーを作成する必要がある場合があります。Spring Data REST の設定、メッセージコンバーター、例外処理などを利用するには、標準の Spring MVC @Controller
または @RestController
の代わりに @RepositoryRestController
アノテーションを使用します。@RepositoryRestController
でアノテーションが付けられたコントローラーは、他のすべての RESTful エンドポイント (たとえば、/api
) によって使用される RepositoryRestConfiguration.setBasePath
で定義された API ベースパスから提供されます。次の例は、@RepositoryRestController
アノテーションの使用方法を示しています。
@RepositoryRestController
class ScannerController {
private final ScannerRepository repository;
ScannerController(ScannerRepository repository) { (1)
this.repository = repository;
}
@GetMapping(path = "/scanners/search/producers") (2)
ResponseEntity<?> getProducers() {
List<String> producers = repository.listProducers(); (3)
// do some intermediate processing, logging, etc. with the producers
CollectionModel<String> resources = CollectionModel.of(producers); (4)
resources.add(linkTo(methodOn(ScannerController.class).getProducers()).withSelfRel()); (5)
// add other links as needed
return ResponseEntity.ok(resources); (6)
}
}
1 | この例では、コンストラクターインジェクションを使用しています。 |
2 | このハンドラーは、カスタムハンドラーメソッドをクエリメソッドリソースとしてプラグインします。 |
3 | このハンドラーは、基になるリポジトリを使用してデータをフェッチしますが、最終的なデータセットをクライアントに返す前に何らかの形の後処理を実行します。 |
4 | 型 T の結果は、コレクションを返すために Spring HATEOAS CollectionModel<T> オブジェクトにラップする必要があります。EntityModel<T> または RepresentationModel<T> は、それぞれ単一のアイテムに適したラッパーです。 |
5 | この正確なメソッドへのリンクを self リンクとして追加します。 |
6 | Spring MVC の ResponseEntity ラッパーを使用してコレクションを返すと、コレクションが適切にラップされ、適切な受け入れ型でレンダリングされます。 |
CollectionModel
はコレクション用ですが、EntityModel
(またはより一般的なクラス RepresentationModel
)は単一のアイテム用です。これらの型は組み合わせることができます。コレクション内の各アイテムのリンクがわかっている場合は、CollectionModel<EntityModel<String>>
(または String
ではなくコアドメイン型)を使用してください。そうすることで、コレクション全体だけでなく、各アイテムのリンクを組み立てることができます。
この例では、結合されたパスは RepositoryRestConfiguration.getBasePath() + /scanners/search/producers です。 |
集約参照の取得
PUT
および POST
リクエストを受信するカスタムコントローラーの場合、通常、リクエスト本文には、URI を使用して他のリソースへの参照を表現する JSON ドキュメントが含まれます。GET
リクエストの場合、それらの参照はリクエストパラメーターを介して渡されます。
Spring Data REST 4.1 では、このような参照をキャプチャーし、参照先の集約の識別子、集約自体、jMolecules Association
のいずれかに解決するためのハンドラーメソッドパラメーター型として AggregateReference<T, ID>
が提供されています。必要なのは、その型の @RequestParam
を宣言し、識別子または完全に解決された集約のいずれかを使用することだけです。
@RepositoryRestController
class ScannerController {
private final ScannerRepository repository;
ScannerController(ScannerRepository repository) {
this.repository = repository;
}
@GetMapping(path = "/scanners")
ResponseEntity<?> getProducers(
@RequestParam AggregateReference<Producer, ProducerIdentifier> producer) {
var identifier = producer.resolveRequiredId();
// Alternatively
var aggregate = producer.resolveRequiredAggregate();
}
// Alternatively
@GetMapping(path = "/scanners")
ResponseEntity<?> getProducers(
@RequestParam AssociationAggregateReference<Producer, ProducerIdentifier> producer) {
var association = producer.resolveRequiredAssociation();
}
}
jMolecules を使用している場合、AssociationAggregateReference
を使用して Association
を取得することもできます。両方の抽象化では、パラメーターの値が、Spring Data REST がアイテムリソースを公開するために使用するスキームに一致する URI であると想定していますが、参照インスタンスで … .withIdSource(…)
を呼び出して、受信した URI から取得した UriComponents
から最終的に集約解決に使用される識別子値を抽出する関数を提供することで、ソース値の解決をカスタマイズできます。
@RepositoryRestController
VS. @BasePathAwareController
エンティティ固有の操作に関心がなくても、Spring MVC ビュー、リソースなどの basePath
にカスタム操作を構築したい場合は、@BasePathAwareController
を使用してください。カスタムコントローラーで @RepositoryRestController
を使用している場合、リクエストマッピングがリポジトリで使用される URI スペースに融合する場合にのみ、リクエストを処理します。また、次の追加機能をコントローラーメソッドに適用します。
ハンドラーメソッドのリクエストマッピングで使用されるベースパスセグメントにマッピングされたリポジトリに対して定義された CORS 構成。
JPA を使用する場合は、
OpenEntityManagerInViewInterceptor
を適用して、遅延解決としてマークされたプロパティにアクセスできるようにします。
何かに @Controller または @RestController を使用する場合、そのコードは完全に Spring Data REST の範囲外です。これは、リクエスト処理、メッセージコンバーター、例外処理、その他の用途にまでおよびます。 |