【问题标题】:Spring WebSockets - how to apply @DestinationVariable only to @SendTo annotation?Spring WebSockets - 如何仅将@DestinationVariable 应用于@SendTo 注释?
【发布时间】:2018-09-16 09:14:23
【问题描述】:

我正在尝试将目标变量应用于我的控制器中处理来自 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]

我的问题是:我想实现的目标有可能吗?

【问题讨论】:

  • 我不认为这是一种不同的情况,只是您试图在错误的上下文中使用@DestinationVariable@DestinationVariable 只能用于@MessageMapping / @SubscribeMapping 中的占位符,而不能用于@SendTo。错误是抱怨你想得到一个叫做“id”的东西,但你没有在你的目的地定义它。为了将具有不同占位符的动态返回目的地作为原始目的地,您必须使用 MessagingTemplate。

标签: spring spring-mvc websocket spring-websocket spring-4


【解决方案1】:

您收到的错误是告诉您目的地中没有名为 id 的占位符(在您的 @MessageMapping 中定义)。 @DestinationVariable 尝试从传入目的地获取变量,它不像您尝试的那样绑定到传出目的地。但是,您可以在 @SendTo 内部使用来自目标位置的相同占位符 @MessageMapping(但这不是您的情况)。

如果您想拥有动态目的地,请使用 MessagingTemplate 之类的:

@MessageMapping("/lock-document")
public void response(Message message) {
    simpMessagingTemplate.convertAndSend("/notify-open-documents/" + message.getDocumentId(), new Response(message.getDocumentId());
}

【讨论】:

  • 谢谢@Sergi!看完你的回答我就知道问题出在哪里了!
【解决方案2】:

这应该是可能的。我指的是以下答案: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);
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2016-06-05
  • 2015-01-18
  • 1970-01-01
  • 2013-01-21
  • 2019-07-21
  • 2016-12-16
  • 1970-01-01
  • 2015-09-15
相关资源
最近更新 更多