アノテーション付きコントローラー
アプリケーションは、アノテーション付きの @Controller
クラスを使用して、クライアントからのメッセージを処理できます。このようなクラスは、次のトピックに従って、@MessageMapping
、@SubscribeMapping
、@ExceptionHandler
メソッドを宣言できます。
@MessageMapping
@MessageMapping
を使用して、宛先に基づいてメッセージをルーティングするメソッドにアノテーションを付けることができます。メソッドレベルおよび型レベルでサポートされています。型レベルでは、@MessageMapping
を使用して、コントローラーのすべてのメソッドで共有マッピングを表現します。
デフォルトでは、マッピング値は Ant スタイルのパスパターン(たとえば、/thing*
、/thing/**
)であり、テンプレート変数(たとえば、/thing/{id}
)のサポートが含まれています。値は、@DestinationVariable
メソッド引数を介して参照できます。セパレーターとしてのドットに従って、アプリケーションは、マッピングのためにドットで区切られた宛先規則に切り替えることもできます。
サポートされているメソッド引数
次の表で、メソッドの引数について説明します。
メソッド引数 | 説明 |
---|---|
| 完全なメッセージにアクセスするため。 |
|
|
| 型指定されたアクセサーメソッドを介してヘッダーにアクセスします。 |
| 構成された デフォルトでは、他の引数が一致しない場合に想定されるため、このアノテーションの存在は必要ありません。 ペイロード引数に |
| 必要に応じて |
| メッセージ内のすべてのヘッダーにアクセスします。この引数は |
| メッセージ宛先から抽出されたテンプレート変数へのアクセス用。必要に応じて、値は宣言されたメソッドの引数型に変換されます。 |
| WebSocket HTTP ハンドシェイク時にログインしたユーザーを反映します。 |
戻り値
デフォルトでは、@MessageMapping
メソッドからの戻り値は、一致する MessageConverter
を介してペイロードに直列化され、Message
として brokerChannel
に送信され、そこからサブスクライバーにブロードキャストされます。送信メッセージの宛先は、受信メッセージの宛先と同じですが、接頭辞 /topic
が付いています。
@SendTo
および @SendToUser
アノテーションを使用して、出力メッセージの宛先をカスタマイズできます。@SendTo
は、ターゲット宛先をカスタマイズするため、または複数の宛先を指定するために使用されます。@SendToUser
は、入力メッセージに関連付けられたユーザーのみに出力メッセージを送信するために使用されます。ユーザー宛先を参照してください。
同じメソッドで @SendTo
と @SendToUser
の両方を同時に使用できます。両方ともクラスレベルでサポートされます。この場合、クラスのメソッドのデフォルトとして機能します。ただし、メソッドレベルの @SendTo
または @SendToUser
アノテーションは、クラスレベルでこのようなアノテーションをオーバーライドすることに注意してください。
メッセージは非同期で処理でき、@MessageMapping
メソッドは ListenableFuture
、CompletableFuture
、CompletionStage
を返すことができます。
@SendTo
と @SendToUser
は、単に SimpMessagingTemplate
を使用してメッセージを送信することに相当する利便性にすぎないことに注意してください。必要に応じて、より高度なシナリオでは、@MessageMapping
メソッドは SimpMessagingTemplate
を直接使用してフォールバックできます。これは、値を返す代わりに、または値を返すことに加えて行うことができます。メッセージ送信を参照してください。
@SubscribeMapping
@SubscribeMapping
は @MessageMapping
に似ていますが、マッピングをサブスクリプションメッセージのみに絞り込みます。@MessageMapping
と同じメソッド引数をサポートします。ただし、戻り値の場合、デフォルトでは、メッセージはクライアントに直接送信され(サブスクリプションに応じて clientOutboundChannel
を介して)、ブローカーではなく(一致するサブスクリプションへのブロードキャストとして) brokerChannel
を介して送信されます。@SendTo
または @SendToUser
を追加すると、この動作がオーバーライドされ、代わりにブローカーに送信されます。
これはいつ便利ですか? ブローカーは /topic
および /queue
にマップされ、アプリケーションコントローラーは /app
にマップされると仮定します。このセットアップでは、ブローカーは /topic
および /queue
へのすべてのサブスクリプションを保存します。これらのサブスクリプションは、繰り返しブロードキャストするためのものであり、アプリケーションが関与する必要はありません。クライアントは /app
の宛先にサブスクライブすることもでき、コントローラーは、サブスクリプションを格納または使用せずにブローカーを関与させることなく、そのサブスクリプションに応じて値を返すことができます(事実上、1 回限りのリクエストレスポンス交換)。この使用例の 1 つは、起動時に UI に初期データを入力することです。
これが役に立たないのはいつですか? 何らかの理由で、サブスクリプションを含むメッセージを両方とも独立して処理する場合を除き、ブローカーとコントローラーを同じ宛先プレフィックスにマップしようとしないでください。受信メッセージは並行して処理されます。ブローカーまたはコントローラーが指定されたメッセージを最初に処理するかどうかの保証はありません。サブスクリプションが保存され、ブロードキャストの準備ができたときにゴールを通知する場合、クライアントは、サーバーがそれをサポートしているかどうかを確認する必要があります(単純なブローカーはサポートしていません)。例: Java STOMP クライアントでは、次を実行して領収書を追加できます。
@Autowired
private TaskScheduler messageBrokerTaskScheduler;
// During initialization..
stompClient.setTaskScheduler(this.messageBrokerTaskScheduler);
// When subscribing..
StompHeaders headers = new StompHeaders();
headers.setDestination("/topic/...");
headers.setReceipt("r1");
FrameHandler handler = ...;
stompSession.subscribe(headers, handler).addReceiptTask(receiptHeaders -> {
// Subscription ready...
});
サーバー側のオプションは、ExecutorChannelInterceptor
を brokerChannel
に登録し、サブスクリプションを含むメッセージが処理された後に呼び出される afterMessageHandled
メソッドを実装することです。
@MessageExceptionHandler
アプリケーションは、@MessageExceptionHandler
メソッドを使用して、@MessageMapping
メソッドからの例外を処理できます。例外インスタンスへのアクセスを取得する場合は、アノテーション自体で例外を宣言するか、メソッド引数を使用して例外を宣言できます。次の例では、メソッド引数を介して例外を宣言しています。
@Controller
public class MyController {
// ...
@MessageExceptionHandler
public ApplicationError handleException(MyException exception) {
// ...
return appError;
}
}
@MessageExceptionHandler
メソッドは、柔軟なメソッドシグネチャーをサポートし、@MessageMapping
メソッドと同じメソッド引数型と戻り値をサポートします。
通常、@MessageExceptionHandler
メソッドは、それが宣言されている @Controller
クラス (またはクラス階層) 内に適用されます。このようなメソッドをよりグローバルに (コントローラー間で) 適用したい場合は、@ControllerAdvice
でマークされたクラスでメソッドを宣言できます。これは、Spring MVC で利用できる同様のサポートに相当します。