带注释的控制器
应用程序可以使用带注释的@Controller
类来处理来自客户端的消息。
此类可以声明@MessageMapping
,@SubscribeMapping
和@ExceptionHandler
方法,如以下主题所述:
@MessageMapping
您可以使用@MessageMapping
来注释根据其
目的地。它在方法级别和类型级别都受支持。在类型
水平@MessageMapping
用于表示
控制器。
默认情况下,映射值为 Ant 样式的路径模式(例如/thing*
,/thing/**
),
包括对模板变量的支持(例如/thing/{id}
).值可以是
引用方式@DestinationVariable
method 参数。应用程序还可以切换到
映射的点分隔目标约定,如 点作为分隔符中所述。
支持的方法参数
下表描述了方法参数:
Method 参数 | 描述 |
---|---|
|
用于访问完整的消息。 |
|
要访问 |
|
用于通过类型化访问器方法访问标头。 |
|
要访问消息的有效负载,请由配置的 此注释的存在不是必需的,因为默认情况下,如果不存在 other 参数。 您可以使用 |
|
要访问特定的标头值,以及使用 |
|
用于访问消息中的所有标头。此参数必须可分配给 |
|
用于访问从消息目标提取的模板变量。 值将根据需要转换为声明的方法参数类型。 |
|
反映在 WebSocket HTTP 握手时登录的用户。 |
返回值
默认情况下,来自@MessageMapping
method 序列化为有效负载
通过匹配的MessageConverter
并作为Message
到brokerChannel
,
从那里向订阅者广播。出站消息的目的地是
与入站消息的 ID 相同,但前缀为/topic
.
您可以使用@SendTo
和@SendToUser
annotations 自定义
输出消息。@SendTo
用于自定义目标目标或
指定多个目标。@SendToUser
用于定向输出消息
仅与输入消息关联的用户。请参阅 用户目标。
您可以同时使用@SendTo
和@SendToUser
同时使用相同的方法,并且两者
在类级别受支持,在这种情况下,它们充当
类。但是,请记住,任何方法级别的@SendTo
或@SendToUser
附注
在类级别覆盖任何此类注释。
消息可以异步处理,并且@MessageMapping
method 可以返回ListenableFuture
,CompletableFuture
或CompletionStage
.
请注意,@SendTo
和@SendToUser
只是一种方便,相当于使用SimpMessagingTemplate
以发送消息。如有必要,对于更高级的场景,@MessageMapping
方法可以回退到使用SimpMessagingTemplate
径直。
这可以代替返回值,也可能同时返回值。
请参阅发送消息。
@SubscribeMapping
@SubscribeMapping
类似于@MessageMapping
但将映射缩小到
仅限订阅消息。它支持与@MessageMapping
.然而
对于返回值,默认情况下,消息将直接发送到客户端(通过clientOutboundChannel
响应订阅)而不是代理(通过brokerChannel
作为对匹配订阅的广播)。添加@SendTo
或@SendToUser
覆盖此行为并改为发送到 broker。
这在什么情况下有用?假设代理映射到/topic
和/queue
而
应用程序控制器映射到/app
.在此设置中,代理存储所有
订阅/topic
和/queue
用于重复广播的 URL,以及
应用程序无需参与。客户端还可以订阅
一些/app
destination 的 Destination 中,控制器可以返回一个值来响应该
订阅,而不涉及代理,而无需再次存储或使用订阅
(实际上是一次性的请求-回复交换)。其中一个用例是填充 UI
使用启动时的初始数据。
这在什么情况下没有用?不要尝试将 broker 和 controller 映射到同一个目的地 前缀,除非您希望两者都独立处理消息(包括订阅)、 出于某种原因。入站消息是并行处理的。无法保证 broker 或 controller 首先处理给定的消息。如果目标是收到通知 当订阅存储并准备好进行广播时,客户端应请求 receipt (如果服务器支持) (Simple Broker 不支持)。例如,使用 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
方法。您可以在 annotation 中声明异常
本身或通过 method 参数(如果你想访问异常实例)。
下面的示例通过 method 参数声明一个 exception:
@Controller
public class MyController {
// ...
@MessageExceptionHandler
public ApplicationError handleException(MyException exception) {
// ...
return appError;
}
}
@MessageExceptionHandler
方法支持灵活的方法签名和支持
方法参数类型和返回值与@MessageMapping
方法。
通常@MessageExceptionHandler
方法在@Controller
类
(或类层次结构)中声明它们。如果您希望此类方法适用
更全局地(跨控制器),您可以在标有@ControllerAdvice
.这与 Spring MVC 中提供的类似支持相当。