アノテーション付きコントローラー

アプリケーションは、アノテーション付きの @Controller クラスを使用して、クライアントからのメッセージを処理できます。このようなクラスは、次のトピックに従って、@MessageMapping@SubscribeMapping@ExceptionHandler メソッドを宣言できます。

@MessageMapping

@MessageMapping を使用して、宛先に基づいてメッセージをルーティングするメソッドにアノテーションを付けることができます。メソッドレベルおよび型レベルでサポートされています。型レベルでは、@MessageMapping を使用して、コントローラーのすべてのメソッドで共有マッピングを表現します。

デフォルトでは、マッピング値は Ant スタイルのパスパターン(たとえば、/thing*/thing/**)であり、テンプレート変数(たとえば、/thing/{id})のサポートが含まれています。値は、@DestinationVariable メソッド引数を介して参照できます。セパレーターとしてのドットに従って、アプリケーションは、マッピングのためにドットで区切られた宛先規則に切り替えることもできます。

サポートされているメソッド引数

次の表で、メソッドの引数について説明します。

メソッド引数 説明

Message

完全なメッセージにアクセスするため。

MessageHeaders

Message 内のヘッダーへのアクセス用。

MessageHeaderAccessor, SimpMessageHeaderAccessor, and StompHeaderAccessor

型指定されたアクセサーメソッドを介してヘッダーにアクセスします。

@Payload

構成された MessageConverter によって(たとえば JSON から)変換されたメッセージのペイロードへのアクセス用。

デフォルトでは、他の引数が一致しない場合に想定されるため、このアノテーションの存在は必要ありません。

ペイロード引数に @jakarta.validation.Valid または Spring の @Validated のアノテーションを付けると、ペイロード引数が自動的に検証されます。

@Header

必要に応じて org.springframework.core.convert.converter.Converter を使用した型変換とともに、特定のヘッダー値にアクセスします。

@Headers

メッセージ内のすべてのヘッダーにアクセスします。この引数は java.util.Map に割り当て可能でなければなりません。

@DestinationVariable

メッセージ宛先から抽出されたテンプレート変数へのアクセス用。必要に応じて、値は宣言されたメソッドの引数型に変換されます。

java.security.Principal

WebSocket HTTP ハンドシェイク時にログインしたユーザーを反映します。

戻り値

デフォルトでは、@MessageMapping メソッドからの戻り値は、一致する MessageConverter を介してペイロードに直列化され、Message として brokerChannel に送信され、そこからサブスクライバーにブロードキャストされます。送信メッセージの宛先は、受信メッセージの宛先と同じですが、接頭辞 /topic が付いています。

@SendTo および @SendToUser アノテーションを使用して、出力メッセージの宛先をカスタマイズできます。@SendTo は、ターゲット宛先をカスタマイズするため、または複数の宛先を指定するために使用されます。@SendToUser は、入力メッセージに関連付けられたユーザーのみに出力メッセージを送信するために使用されます。ユーザー宛先を参照してください。

同じメソッドで @SendTo と @SendToUser の両方を同時に使用できます。両方ともクラスレベルでサポートされます。この場合、クラスのメソッドのデフォルトとして機能します。ただし、メソッドレベルの @SendTo または @SendToUser アノテーションは、クラスレベルでこのようなアノテーションをオーバーライドすることに注意してください。

メッセージは非同期で処理でき、@MessageMapping メソッドは ListenableFutureCompletableFutureCompletionStage を返すことができます。

@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 で利用できる同様のサポートに相当します。