此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10spring-doc.cadn.net.cn

带注释的控制器

应用程序可以使用带注释的@Controller类来处理来自客户端的消息。 此类类可以声明@MessageMapping,@SubscribeMapping@ExceptionHandler方法,如以下主题中所述:spring-doc.cadn.net.cn

@MessageMapping

您可以使用@MessageMapping以注释根据其 目的地。它在方法级别和类型级别都受支持。在类型 水平@MessageMapping用于表达 控制器。spring-doc.cadn.net.cn

默认情况下,映射值是 Ant 样式的路径模式(例如/thing*,/thing/**), 包括对模板变量的支持(例如,/thing/{id}).值可以是 引用通过@DestinationVariablemethod 参数。应用程序也可以切换到 映射的点分隔目标约定,如点作为分隔符中所述。spring-doc.cadn.net.cn

支持的方法参数

下表描述了方法参数:spring-doc.cadn.net.cn

方法参数 描述

Messagespring-doc.cadn.net.cn

访问完整消息。spring-doc.cadn.net.cn

MessageHeadersspring-doc.cadn.net.cn

要访问Message.spring-doc.cadn.net.cn

MessageHeaderAccessor,SimpMessageHeaderAccessorStompHeaderAccessorspring-doc.cadn.net.cn

用于通过类型化访问器方法访问标头。spring-doc.cadn.net.cn

@Payloadspring-doc.cadn.net.cn

用于访问消息的有效负载,由配置的MessageConverter.spring-doc.cadn.net.cn

不需要此注释的存在,因为默认情况下,如果没有 其他参数匹配。spring-doc.cadn.net.cn

您可以使用以下命令注释有效负载参数@jakarta.validation.Valid或 Spring 的@Validated, 自动验证有效负载参数。spring-doc.cadn.net.cn

@Headerspring-doc.cadn.net.cn

用于访问特定的标头值 - 以及使用org.springframework.core.convert.converter.Converter,如有必要。spring-doc.cadn.net.cn

@Headersspring-doc.cadn.net.cn

用于访问邮件中的所有标头。此参数必须可分配给java.util.Map.spring-doc.cadn.net.cn

@DestinationVariablespring-doc.cadn.net.cn

用于访问从消息目标提取的模板变量。 根据需要将值转换为声明的方法参数类型。spring-doc.cadn.net.cn

java.security.Principalspring-doc.cadn.net.cn

反映 WebSocket HTTP 握手时登录的用户。spring-doc.cadn.net.cn

返回值

默认情况下,来自@MessageMapping方法序列化为有效负载 通过匹配MessageConverter并作为MessagebrokerChannel, 从那里向订阅者广播。出站消息的目的地是 与入站消息相同,但前缀为/topic.spring-doc.cadn.net.cn

您可以使用@SendTo@SendToUser注释来自定义目标 输出消息。@SendTo用于自定义目标目标或 指定多个目的地。@SendToUser用于引导输出消息 仅与输入消息关联的用户。请参阅用户目标spring-doc.cadn.net.cn

您可以同时使用@SendTo@SendToUser同时在同一个方法上,并且同时 在类级别受支持,在这种情况下,它们充当 类。但是,请记住,任何方法级别@SendTo@SendToUser附注 在类级别覆盖任何此类注释。spring-doc.cadn.net.cn

消息可以异步处理,并且@MessageMapping方法可以返回ListenableFuture,CompletableFutureCompletionStage.spring-doc.cadn.net.cn

请注意@SendTo@SendToUser只是为了方便,相当于使用SimpMessagingTemplate发送消息。如有必要,对于更高级的方案,@MessageMapping方法可以使用SimpMessagingTemplate径直。 这可以代替返回值,或者可以作为返回值的补充。 请参阅发送消息spring-doc.cadn.net.cn

@SubscribeMapping

@SubscribeMapping类似于@MessageMapping但将映射范围缩小为 仅订阅消息。它支持与@MessageMapping.然而 对于返回值,默认情况下,消息直接发送到客户端(通过clientOutboundChannel,以响应订阅)而不是经纪人(通过brokerChannel,作为对匹配订阅的广播)。添加@SendTo@SendToUser覆盖此行为并发送给代理。spring-doc.cadn.net.cn

这在什么时候有用?假设代理映射到/topic/queue而 应用程序控制器映射到/app.在此设置中,代理将所有 订阅/topic/queue用于重复广播,以及 应用程序无需参与。客户端还可以订阅 一些/appdestination,控制器可以返回一个值来响应该值 订阅而不涉及代理,无需再次存储或使用订阅 (实际上是一次性请求-回复交换)。其中一个用例是填充 UI 在启动时使用初始数据。spring-doc.cadn.net.cn

什么时候这没有用?不要尝试将代理和控制器映射到同一目标 prefix,除非你希望两者独立处理消息,包括订阅, 出于某种原因。入站消息是并行处理的。无法保证是否 代理或控制器首先处理给定的消息。如果目标是通知 当订阅存储并准备好进行广播时,客户端应请求 如果服务器支持(Simple Broker 不支持),则接收。例如,使用 Java STOMP 客户端,您可以执行以下作来添加收据:spring-doc.cadn.net.cn

@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...
});

服务器端选项是注册一个ExecutorChannelInterceptorbrokerChannel并实现afterMessageHandled在处理消息(包括订阅)后调用的方法。spring-doc.cadn.net.cn

@MessageExceptionHandler

应用程序可以使用@MessageExceptionHandler处理异常的方法@MessageMapping方法。您可以在注释中声明异常 如果要访问异常实例,则通过方法参数。 以下示例通过方法参数声明异常:spring-doc.cadn.net.cn

@Controller
public class MyController {

	// ...

	@MessageExceptionHandler
	public ApplicationError handleException(MyException exception) {
		// ...
		return appError;
	}
}

@MessageExceptionHandler方法支持灵活的方法签名和支持 相同的方法参数类型和返回值@MessageMapping方法。spring-doc.cadn.net.cn

通常@MessageExceptionHandler方法适用于@Controller类 (或类层次结构),其中声明了它们。如果希望应用此类方法 更全局(跨控制器),您可以在标记为@ControllerAdvice.这与 Spring MVC 中提供的类似支持相当。spring-doc.cadn.net.cn