此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10! |
带注释的控制器
应用程序可以使用带注释的@Controller
类来处理来自客户端的消息。
此类类可以声明@MessageMapping
,@SubscribeMapping
和@ExceptionHandler
方法,如以下主题中所述:
@MessageMapping
您可以使用@MessageMapping
以注释根据其
目的地。它在方法级别和类型级别都受支持。在类型
水平@MessageMapping
用于表达
控制器。
默认情况下,映射值是 Ant 样式的路径模式(例如/thing*
,/thing/**
),
包括对模板变量的支持(例如,/thing/{id}
).值可以是
引用通过@DestinationVariable
method 参数。应用程序也可以切换到
映射的点分隔目标约定,如点作为分隔符中所述。
支持的方法参数
下表描述了方法参数:
方法参数 | 描述 |
---|---|
|
访问完整消息。 |
|
要访问 |
|
用于通过类型化访问器方法访问标头。 |
|
用于访问消息的有效负载,由配置的 不需要此注释的存在,因为默认情况下,如果没有 其他参数匹配。 您可以使用以下命令注释有效负载参数 |
|
用于访问特定的标头值 - 以及使用 |
|
用于访问邮件中的所有标头。此参数必须可分配给 |
|
用于访问从消息目标提取的模板变量。 根据需要将值转换为声明的方法参数类型。 |
|
反映 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
destination,控制器可以返回一个值来响应该值
订阅而不涉及代理,无需再次存储或使用订阅
(实际上是一次性请求-回复交换)。其中一个用例是填充 UI
在启动时使用初始数据。
什么时候这没有用?不要尝试将代理和控制器映射到同一目标 prefix,除非你希望两者独立处理消息,包括订阅, 出于某种原因。入站消息是并行处理的。无法保证是否 代理或控制器首先处理给定的消息。如果目标是通知 当订阅存储并准备好进行广播时,客户端应请求 如果服务器支持(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
方法。您可以在注释中声明异常
如果要访问异常实例,则通过方法参数。
以下示例通过方法参数声明异常:
@Controller
public class MyController {
// ...
@MessageExceptionHandler
public ApplicationError handleException(MyException exception) {
// ...
return appError;
}
}
@MessageExceptionHandler
方法支持灵活的方法签名和支持
相同的方法参数类型和返回值@MessageMapping
方法。
通常@MessageExceptionHandler
方法适用于@Controller
类
(或类层次结构),其中声明了它们。如果希望应用此类方法
更全局(跨控制器),您可以在标记为@ControllerAdvice
.这与 Spring MVC 中提供的类似支持相当。