当前位置: 首页 > 知识库问答 >
问题:

Spring WebSocket-通知订阅者不起作用

端木兴国
2023-03-14

我正在尝试让Spring WebSocket(Spring 4)在我一直在做的项目中工作。到目前为止,我已经打开了WebSocket,添加了订阅者并发送了消息。

从昨天开始,我一直在试图弄清楚为什么我的endpoint不处理HTML中包含的stomp客户端发送的消息。控制台中实际上也没有错误(好吧,我不完全确定这里的“连接到服务器未定义”是什么意思)。

以下是Chrome控制台的输出:

Opening Web Socket...
Web Socket Opened...

>>> CONNECT
accept-version:1.1,1.0
heart-beat:10000,10000

<<< CONNECTED
version:1.1
heart-beat:0,0
user-name:xxx@yyy.com

connected to server undefined

Connected: CONNECTED
user-name:xxx@yyy.com
heart-beat:0,0
version:1.1


>>> SUBSCRIBE
id:sub-0
destination:/my-project/notify-open-documents/1

Sending message : {"documentId":"1"}

>>> SEND
destination:/my-project/ws/lock-document
content-length:19

{"documentId":"1"}

这是我的代码:

配置:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/notify-open-documents");
        registry.setApplicationDestinationPrefixes("/ws");   
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
        stompEndpointRegistry.addEndpoint("/lock-document");
        stompEndpointRegistry.addEndpoint("/lock-document").withSockJS();
    }
}

控制员:

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

以及我的HTML中与跺脚相关的部分:

<script type="text/javascript">

    $(document).ready(function() { 
        connect(); 
    });

    var stompClient = null;

    function connect() {
        var socket = new SockJS('<spring:url value="/lock-document"/>');
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function (frame) {
            console.log('Connected: ' + frame);
            stompClient.subscribe('<spring:url value="/notify-open-documents/${id}"/>', function (messageOutput) {
                console.log('Receiving message: ' + JSON.parse(messageOutput.body));
            });
            sendName();
        });
    }

    function disconnect() {
        if (stompClient !== null) {
            stompClient.disconnect();
        }
        console.log("Disconnected");
    }

    function sendName() {
        console.log("Sending message : " + JSON.stringify({'documentId' : "${id}" }));
        stompClient.send('<spring:url value="/ws/lock-document"/>', {}, JSON.stringify({'documentId': "${id}"}));
    }

</script>

我真的不知道可能出了什么问题,我的浏览器支持WebSocket,从我在日志中看到的,WebSocket正在正确打开,消息正在发送,但我不明白的是为什么我的控制器无法处理传入的消息。

共有1个答案

池永长
2023-03-14

从您的HTML代码片段中,我看到您正在使用spring:url标记生成STOMP目的地。spring:url标记添加了上下文路径,这对于STOMP目的地来说没有意义。

您正在配置的应用程序目标前缀是/ws,代理目标前缀是/enected-open-文档,这些都不匹配您的上下文路径,即/my-project(从控制台输出)。从您的订阅目的地和发送消息时(不是从SockJS URL)删除上下文路径:

stompClient.send('/ws/lock-document', {}, JSON.stringify({'documentId': "${id}"}));
 类似资料:
  • STOMP规范规定订阅必须有id头。 https://stomp.github.io/stomp-specification-1.2.html#SUBSCRIBE_id_Header 订阅id标头 由于单个连接可以与服务器有多个打开的订阅,因此必须在框架中包含id标头以唯一标识订阅。id标头允许客户端和服务器将后续消息或取消订阅帧与原始订阅关联。在同一连接中,不同的订阅必须使用不同的订阅标识符。

  • 主要内容:一、通知,二、源码分析,三、总结一、通知 在Redis中,既可以实现消息的发送又可以实现订阅,也就是常说的发布/订阅。它的主要逻辑实现在nofigy.c和module.c、pubsub.c中,其实通知做为一种辅助功能,是易用性的一种良好的接口。Redis的通知功能是一种即时在线通知功能,如果CS端断线后,相关的消息就无法再次通知,也就是说,消息机制没有保存和重发功能。这也是为了实现设计上的简单和功能实现的鲁棒性的考虑,至于以后会

  • 在运行 ZeroMQ 基本 PUB / SUB C# 示例时,如果我先启动发布服务器,它们对我有用,但如果我先启动订阅服务器,则不会。当我这样做时,订阅者启动,但从未收到任何数据。从我所读到的内容来看,我认为我应该能够以任一顺序启动这些过程。 我正在使用nuget in的ZeroMQ 4.1.0.26软件包。NET 4.6,x64应用程序。这些都是在Windows上运行的。我在同一台机器上运行这两

  • 我使用我的应用程序设置了 Firebase 消息,但不幸的是,通知没有出现。 我正确地设置了Firebase,它连接到我的应用程序,我也发送了一些测试消息,在Firebase中它说已完成,但是我没有在我的手机上收到它们。 我的应用程序还没有上市,我正在通过Android Studio开发和测试它。 这是我的MyFirebaseInstanceIDService类 } 这里来了我的火库消息服务类:

  • 1.手机版 设置方法:订阅号右上角详情-在消息中置顶   2.电脑版 设置方法:订阅号右上角详情-设置-在消息中置顶

  • 我用的是Spring MVC(4.2.2.RELEASE)和Tomcat 8。我的要求是向浏览器发送一个通知。请找到下面的代码。 控制器-------------------@Controller公共类MessageController{/@Autowired private SimpMessageTemplate模板;@Autowire private SimpMessageSendingOpe