本文主要是介绍Spring STOMP-带注解的控制器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
应用程序可以使用带@Controller
注解的类来处理来自客户端的消息。这些类可以声明带@MessageMapping
、@SubscribeMapping
和@ExceptionHandler
注解的方法,如下所述:
@MessageMapping
@SubscribeMapping
@MessageExceptionHandler
@MessageMapping
注释@MessageMapping
注解的方法,能处理对应destination的消息。注解支持方法和类级别。在类级别,@MessageMapping
的配置会在所有方法上共享。
默认情况下,映射值是Ant风格的路径模式(例如/thing*
、/thing/**
),也支持模板变量(例如,/thing/{id}
)。这些值可以通过带@DestinationVariable
注解的方法参数引用。应用程序也可以将destination的映射格式切换到点分隔的形式,如点作为分隔符中解释的一样。
支持的方法参数
下表描述了方法支持的参数:
方法参数 | 描述 |
---|---|
Message | 用于访问完整的消息内容。 |
MessageHeaders | 用于访问消息中的headers信息。 |
MessageHeaderAccessor, SimpMessageHeaderAccessor, and StompHeaderAccessor | 用于通过类型化访问器方法访问headers信息。 |
@Payload | 用于访问消息的payload,通过配置的MessageConverter将payload转换成指定类型(例如,从JSON)。这个注释不是必需显示声明,在没有其他参数匹配时,默认假定参数带了此注解。你可以使用@jakarta.validation.Valid或Spring的@Validated注解来注释payload参数,以自动校验payload参数。 |
@Header | 用于访问指定的header值 - 如果需要,可以使用org.springframework.core.convert.converter.Converter进行类型转换。 |
@Headers | 用于访问消息中的所有headers信息。此参数必须是java.util.Map的子类型。 |
@DestinationVariable | 用于访问消息destination值中的模板变量。根据需要,将值转换为对应方法参数的类型。 |
java.security.Principal | 代表了WebSocket HTTP握手时登录的用户。 |
返回值
默认情况下,@MessageMapping
方法的返回值通过合适的MessageConverter
序列化为payload,作为Message
发送到brokerChannel
,然后广播给订阅者。传出消息的destination值与传入消息的destination值相同,但以/topic
为前缀。
你可以使用@SendTo
和@SendToUser
注解来自定义输出消息的destination。@SendTo
用于自定义指定destination或指定多个destination。@SendToUser
用于将输出消息仅定向到与输入消息关联的用户。见用户目的地。
你可以同时在同一个方法上使用@SendTo
和@SendToUser
,并且两者都支持在类级别上使用,在这种情况下,它们作为类中方法的默认值。然而,要记住任何方法级别的@SendTo
或@SendToUser
注释值都会覆盖类级别上此类注释的值。
消息可以异步处理,@MessageMapping
方法可以返回ListenableFuture
、CompletableFuture
或CompletionStage
类型。
请注意,@SendTo
和@SendToUser
注释仅仅是使用SimpMessagingTemplate
发送消息的便利方式。如果必要,对于更高级的场景,@MessageMapping
方法可以直接使用SimpMessagingTemplate
。这可以作为返回值的替代方案,或者可能作为返回值的补充。见发送消息。
@SubscribeMapping
@SubscribeMapping
类似于@MessageMapping
,但只支持处理订阅消息。它支持与@MessageMapping
相同的方法参数。然而,对于返回值,默认情况下,消息直接发送给客户端(通过clientOutboundChannel
,响应订阅),而不是发送给代理(通过brokerChannel
,作为匹配订阅的广播)。添加@SendTo
或@SendToUser
会覆盖这种行为,会把返回值消息发送给代理。
这在什么时候有用?假设消息代理拦截的destination格式是/topic
和/queue
,而应用程序控制器拦截的格式是/app
。在这种设置中,代理存储所有/topic
和/queue
的订阅,这些订阅旨在进行不断的广播,并且不需要应用程序参与。客户端还可以订阅某些/app
目的地,控制器可以返回值来响应该订阅消息,而不需要涉及代理,不需要存储或再次使用订阅(实际上是一次性的请求-响应交换)。一个用例是在启动时用初始数据填充UI。
这在什么时候没用?不要尝试将消息代理和消息控制器映射到相同的destination前缀,除非出于某种原因,你希望两者都能独立处理消息,包括订阅。传入消息是被并行处理的。无法保证是代理还是控制器首先处理到消息。如果目标是在订阅存储并准备好广播时收到通知,如果服务器支持的话(简单代理不支持),客户端应该请求收据。例如,使用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...*
});
服务端选项是在brokerChannel
上注册一个ExecutorChannelInterceptor
,并实现在处理完消息(包括订阅)后调用的afterMessageHandled
方法。
@MessageExceptionHandler
应用程序可以使用@MessageExceptionHandler
方法来处理来自@MessageMapping
方法抛出的异常。您可以在注解上声明异常,也可以通过方法参数来获取异常实例的访问权限。以下示例展示通过方法参数来声明异常:
@Controller
public class MyController {*// ...*@MessageExceptionHandlerpublic ApplicationError handleException(MyException exception) {*// ...*return appError;}
}
@MessageExceptionHandler
方法支持灵活的方法签名,并支持与@MessageMapping
方法相同的方法参数类型和返回值。
通常,@MessageExceptionHandler
方法适用于它所在的@Controller
类(或类层次结构)中的异常。如果你希望这些方法可以全局使用(跨控制器),你可以在用@ControllerAdvice
标记的类中声明它们。这类似于Spring MVC中提供的类似支持。
这篇关于Spring STOMP-带注解的控制器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!