【stomp 实战】Spring websocket使用详解和基本原理

发布于:2024-04-30 ⋅ 阅读:(35) ⋅ 点赞:(0)

spring框架对websocket有很好的支持,stomp协议作为websocket的子协议,Spring也做了很多封装,让我们在开发中易于使用。
学习使用Spring的Websocket模块,当然最好的办法就是看官网说明了。本篇文章对官网做一些简述和个人的理解。

开始使用

依赖引入

第一步当然是引入SpringBoot的包了

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

这个包实际上引入了两个依赖spring-messaging 和 spring-websocket

如何开启stomp的支持

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		registry.addEndpoint("/portfolio"); 
	}

	@Override
	public void configureMessageBroker(MessageBrokerRegistry config) {
		config.setApplicationDestinationPrefixes("/app"); 
		config.enableSimpleBroker("/topic", "/queue"); 
	}
}
  • registry.addEndpoint(“/portfolio”); 添加一个后端,前端可以通过这个端点,进行websocket通信
    对应的前端代码可以这么写
 var socket = new SockJS('/portfolio');
 stompClient = Stomp.over(socket);
  • config.setApplicationDestinationPrefixes(“/app”); 这个是前端可以往这个路径发送消息。
    前端代码这么写的:
 stompClient.send("/app/echo", {}, JSON.stringify(msg));

后端可以定义一个controller,来接收这个消息,所以这个/app的意思可以理解为所有@MessageMapping的前缀。

@Controller
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class StompController {
    @MessageMapping("/echo")
    public void echo(Principal principal, Msg msg) {
    //代码略
    }
}
  • config.enableSimpleBroker(“/topic”, “/queue”); 这个是启用消息broker。广播消息的前缀。当我们需要发送广播消息给客户端时,需要满足这个前缀条件。
    前端这么订阅消息,是topic前缀
 //订阅广播消息topic
 stompClient.subscribe("/topic/boardCast/hello", function (response) {
 });

后端代码通过消息broker,可以将此消息发送给订阅了"/topic/boardCast/hello"的客户端。

public class StompController {
    private final SimpMessageSendingOperations msgOperations;
    public void test(message) {
        msgOperations.send("/topic/boardCast/hello",message);

    }
}

消息的流转过程

首先得理解以下几个概念

  • Message: 消息,包括消息头和消息体.
  • MessageHandler: 处理消息的处理器
  • MessageChannel:消息通道,客户端发送消息,到达服务器(inboundChannel)。服务器通过通道(outboundChannel)发送消息给客户端
  • MessageBroker:消息分发的处理器,消息怎么流转,是由broker分发的

在这里插入图片描述
代码示例
前端往/app/echo发送了一条消息

    //主动发送消息给服务器,对应的后端topic为/app/echo2
    function send() {
        var value = document.getElementById("content").value;
        var msg = {
            msgType: 1,
            content: value
        };
        stompClient.send("/app/echo2", {}, JSON.stringify(msg));
    }

后端代码得注册/app前缀

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
	@Override
	public void configureMessageBroker(MessageBrokerRegistry config) {
		config.setApplicationDestinationPrefixes("/app"); 
		config.enableSimpleBroker("/topic", "/queue"); 
	}
}

然后定义一个Controller来接收用户消息, @MessageMapping(“/echo”),这里就是子路径了,拼起来正好是/app/echo,这时Wesocket请求会到达echo方法。

@Controller
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class StompController {
    private final SimpMessageSendingOperations msgOperations;
    @MessageMapping("/echo2")
    public void echo2() {
        msgOperations.convertAndSend("/topic/boardCast/hello", "hello boardCast Message");
    }
}

上面示例代码的执行流程,消息的流转如下图所示
在这里插入图片描述

  • 消息通过inboundChannel到服务器
  • 此时根据消息的前缀,会匹配出/app开头的,是需要找SimpAnnotationMethodMessageHandler。这个处理器,是找Controller来执行
  • Controller中收到该消息,其方法中调用了一个发送方法。发往/topic/boardCast/hello
  • 此时也会根据消息的前缀,找到消息处理器,SimpleBrokerMessageHandler
  • SimpleBrokerMessageHandler遍历用户会话,找到订阅了/topic/boardCast/hello的用户。通过outboundChannel将消息发送出去

以上就是用户发送一个消息,服务端接收。服务端同时再发送一条广播消息给对应的客户端的过程。

总结

通过本节内容,我们学到了以下内容

  • 几个配置的含义
    • registry.addEndpoint(“/portfolio”); 配置WebSocket端点
    • config.setApplicationDestinationPrefixes(“/app”); 配置Controller的目的前缀。这是用于服务端接收客户端消息的前缀
    • config.enableSimpleBroker(“/topic”, “/queue”); 配置用户可以订阅的destination。服务端通过msgOperations.convertAndSend(“/topic/boardCast/hello”, “hello boardCast Message”);可以发送消息给订阅了此destination的用户
  • 消息的流转过程,大家可以根据上面的流程图,阅读一下源码

本节的示例源码,都在开源项目中:文章链接【stomp实战】搭建一套websocket推送平台。文章最后有项目地址。