Spring WebSockets - 如何仅将@DestinationVariable应用于@SendTo注释?

4

我正在尝试将一个目标变量应用到我的控制器中处理来自WebSocket的传入消息的方法。这是我想要实现的:

@Controller
public class DocumentWebsocketController {

    @MessageMapping("/lock-document")
    @SendTo("/notify-open-documents/{id}")
    public Response response(@DestinationVariable("id") Long id, Message message) {
        return new Response(message.getDocumentId());
    }
}

问题在于,目标变量仅应用于@SendTo注释。 这将导致在尝试访问此端点时出现以下堆栈跟踪:
12:36:43.044 [clientInboundChannel-7] ERROR org.springframework.web.socket.messaging.WebSocketAnnotationMethodMessageHandler - Unhandled exception
org.springframework.messaging.MessageHandlingException: Missing path template variable 'id' for method parameter type [class java.lang.Long]
    at org.springframework.messaging.handler.annotation.support.DestinationVariableMethodArgumentResolver.handleMissingValue(DestinationVariableMethodArgumentResolver.java:70) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.handler.annotation.support.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:96) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]

(...)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_144]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_144]

我的问题是:我想要实现的这种功能是否可能?

可能是Spring WebSockets @SendTo映射中的路径变量的重复问题。 - Sergi Almar
我不认为这是一个不同的情况,只是你试图在错误的上下文中使用@DestinationVariable@DestinationVariable只能用于@MessageMapping / @SubscribeMapping中的占位符,而不能用于@SendTo中。错误提示说你想要获取一个叫做“id”的东西,但你没有在目标中定义它。为了拥有一个动态返回目标,其中包含与原始目标不同的占位符,你必须使用MessagingTemplate。 - Sergi Almar
2个回答

4
这应该是可行的。我指的是以下回答:Path variables in Spring WebSockets @SendTo mapping 更新:在Spring 4.2中,支持目标变量占位符,现在可以做到这样:
@MessageMapping("/fleet/{fleetId}/driver/{driverId}")
@SendTo("/topic/fleet/{fleetId}")
public Simple simple(@DestinationVariable String fleetId, @DestinationVariable String driverId) {
    return new Simple(fleetId, driverId);
}

这是关于此请求的链接:https://github.com/spring-projects/spring-framework/issues/16784 - lazydev

4
你收到的错误提示告诉你,在你的目标地址(在你的@MessageMapping中定义)里没有叫做id的占位符。 @DestinationVariable试图从传入的目标地址中获取变量,而它并没有绑定到你尝试的传出目标地址。但是,你可以在@SendTo内部使用来自目标地址的同样的占位符(但这不是你的情况)。
如果你想要一个动态的目标地址,可以使用MessagingTemplate,例如:
@MessageMapping("/lock-document")
public void response(Message message) {
    simpMessagingTemplate.convertAndSend("/notify-open-documents/" + message.getDocumentId(), new Response(message.getDocumentId());
}

谢谢@Sergi!阅读了您的答案后,我知道问题出在哪里了,谢谢! - pidabrow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接