9

我通过 SockJS 通过 STOMP 连接到我的 Spring 后端。一切正常,配置适用于所有浏览器等。但是,我找不到发送初始消息的方法。情况如下:

  1. 客户端连接到主题
    函数连接(){
        var socket = new SockJS('http://localhost:8080/myEndpoint');
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function(frame) {
            设置连接(真);
            console.log('已连接:' + frame);
            stompClient.subscribe('/topic/notify', function(message){
                showMessage(JSON.parse(message.body).content);
            });
        });
    }

后端配置看起来或多或少像这样:

    @配置
    @EnableWebSocketMessageBroker
    公共类 WebSocketAppConfig 扩展 AbstractWebSocketMessageBrokerConfigurer {   
    ...
    @覆盖
    公共无效 registerStompEndpoints(最终 StompEndpointRegistry 注册表){
        registry.addEndpoint("/myEndpoint").withSockJS();
    }

  1. I want to send to the client an automatic reply from the backend (on the connection event) so that I can already provide him with some dataset (e.g. read sth from the db) without the need for him (the client) to send a GET request (or any other). So to sum up, I just want to send him a message on the topic with the SimMessagingTemplate object just after he connected.

Usually I do it the following way, e.g. in a REST controller, when the template is already autowired:

    @Autowired
    private SimpMessagingTemplate template;
    ...
    template.convertAndSend(TOPIC, new Message("it works!"));

How to achieve this on connect event?

UPDATE

I have managed to make it work. However, I am still a bit confused with the configuration. I will show here 2 configurations how the initial message can be sent:

1) First solution

JS part

stompClient.subscribe('/app/pending', function(message){
    showMessage(JSON.parse(message.body).content);
});
stompClient.subscribe('/topic/incoming', function(message){
    showMessage(JSON.parse(message.body).content);
});

Java part

@Controller
public class WebSocketBusController {
    @SubscribeMapping("/pending")

Configuration

@Override
public void configureMessageBroker(final MessageBrokerRegistry config) {
    config.enableSimpleBroker("/topic");
    config.setApplicationDestinationPrefixes("/app");
}

...和其他电话

template.convertAndSend("/topic/incoming", outgoingMessage);

2)第二种解决方案

JS部分

stompClient.subscribe('/topic/incoming', function(message){
    showMessage(JSON.parse(message.body).content);
})

Java部分

@Controller
public class WebSocketBusController {
    @SubscribeMapping("/topic/incoming")

配置

@Override
public void configureMessageBroker(final MessageBrokerRegistry config) {
    config.enableSimpleBroker("/topic");
    // NO APPLICATION PREFIX HERE
}

...和其他电话

template.convertAndSend("/topic/incoming", outgoingMessage);

概括:

第一种情况使用两个订阅——我想避免这种情况,并认为这可以只用一个来管理。

然而,第二个没有应用前缀。但至少我可以有一个订阅来收听提供的主题以及发送初始消息。

4

2 回答 2

6

如果您只想在连接时向客户端发送消息,请使用适当的 ApplicationListener:

@Component
public class StompConnectedEvent implements ApplicationListener<SessionConnectedEvent> {

    private static final Logger log = Logger.getLogger(StompConnectedEvent.class);

    @Autowired
    private Controller controller;

    @Override
    public void onApplicationEvent(SessionConnectedEvent event) {
        log.debug("Client connected.");
        // you can use a controller to send your msg here
    }
}
于 2017-01-26T11:49:16.897 回答
3

您不能在 上执行此操作connect,但是@SubscribeMapping在这种情况下可以执行此操作。

您只需要使用该注释标记服务方法,它就会将结果返回给subscribe函数。

来自 Spring 参考手册:

@SubscribeMapping 注解也可用于将订阅请求映射到 @Controller 方法。它在方法级别上受支持,但也可以与类型级别 @MessageMapping 注释结合使用,该注释表示同一控制器内所有消息处理方法之间的共享映射。

默认情况下,@SubscribeMapping 方法的返回值作为消息直接发送回连接的客户端,并且不通过代理。这对于实现请求-回复消息交互很有用;例如,在初始化应用程序 UI 时获取应用程序数据。或者,@SubscribeMapping 方法可以使用@SendTo 进行注释,在这种情况下,使用指定的目标目的地将生成的消息发送到“brokerChannel”。

更新

参考这个例子:https://github.com/revelfire/spring4Test当 index.html 的第 24 行被调用时怎么可能发送任何东西: stompClient.subscribe('/user/queue/socket/responses' ...来自弹簧控制器?

好吧,看起来像这样:

@SubscribeMapping("/queue/socket/responses")
public List<Employee> list() {
     return getEmployees();
}

Stomp 客户端部分保持不变。

于 2014-07-15T11:06:48.693 回答