此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.0spring-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

Method 参数 描述

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

此注释的存在不是必需的,因为默认情况下,如果不存在 other 参数。spring-doc.cadn.net.cn

您可以使用@jakarta.validation.Valid或 Spring 的@Validated, 以自动验证 payload 参数。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

返回值

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

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

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

消息可以异步处理,并且@MessageMappingmethod 可以返回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覆盖此行为并改为发送到 broker。spring-doc.cadn.net.cn

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

这在什么情况下没有用?不要尝试将 broker 和 controller 映射到同一个目的地 前缀,除非您希望两者都独立处理消息(包括订阅)、 出于某种原因。入站消息是并行处理的。无法保证 broker 或 controller 首先处理给定的消息。如果目标是收到通知 当订阅存储并准备好进行广播时,客户端应请求 receipt (如果服务器支持) (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方法。您可以在 annotation 中声明异常 本身或通过 method 参数(如果你想访问异常实例)。 下面的示例通过 method 参数声明一个 exception: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