问题导入
系统运行过程中出现了由主持人的操作推动会议流程的场景,如何将主持人的命令通过服务器同步到每个人的设备上?
问题分析
在当前的系统设计中使用了C/S架构,基本上所有的请求都是终端通过http协议向服务器提出的,而服务器没有办法向终端主动发送消息。
备选方案
- 终端开启端口监听,运行服务器主动发起连接
- 终端轮询查询是否出现状态更新
- 使用WebSocket建立长连接
由于主持人的命令发送具有时间随机、数量少、要求相应速度等要求。耗费大量资源的轮询和终端监听方案被排除。
具体实现
WebSocket协议是一种相当低级的协议。它定义了如何将字节流转换为帧。帧可以包含文本或二进制消息。但是对于参与通信设备的管理功能并没有涉及,例如本场景中所需求的广播支持。经过分析,我们决定使用基于WebSocket协议的协议STOMP来实现这个功能。
导入依赖
使用maven添加依赖
注册endPoint
注册EndPoint给出设备连接stomp的地址,同时绑定一个消息代理用于处理消息。
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket").setAllowedOriginPatterns("*").withSockJS();
}
}
设置频道
通过注解来绑定通信所需要的频道,所有订阅频道的设备在该频道上消息广播时都等接收到。
private SimpMessageSendingOperations simpMessageSendingOperations;
@MessageMapping("/sendCmd")
@SendTo("/topic/cmd")
public Command sendCommand(Command cmd){
return new Command(cmd);
}
设定命令格式
频道上的消息格式设定为code+message。在方便程序处理的同时增强可读性。
public class Command {
String cmd;
int code;
public Command() {
}
public Command(Command cmd) {
this.code = cmd.code;
this.cmd = cmd.cmd;
}
public Command(int code, String cmd) {
this.cmd = cmd;
this.code = code;
}
}
使用Stomp推送消息
使用sendMessage提供服务,下面是开关程序限制的实现代码。
public State changeMode(int mode){
if(mode==0){
state.setState("open");
sendMessage(new Command(1,"腾讯会议开启"));
}else{
state.setState("close");
sendMessage(new Command(2,"腾讯会议关闭"));
}
return state;
}