找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

478

积分

0

好友

60

主题
发表于 昨天 23:23 | 查看: 11| 回复: 0

在消防设备巡检等物联网或业务监控场景中,常需实现服务端主动向客户端推送消息的能力。例如,当巡检员通过手机提交设备异常时,后台的监控大屏需要实时获取该设备信息并高亮显示,以便调度处理。这种对实时性要求高的场景,正是 WebSocket 技术大显身手的地方。

关于 WebSocket 协议的基础知识,可参考 MDN官方文档

本文将通过一个简化的示例,演示如何使用 SpringBoot 快速集成 WebSocket,构建一个后端主动推送、前端实时响应的业务异常监控面板。前端部分为了聚焦核心流程,将使用 Vue 进行数据绑定和样式呈现,省略复杂的地图渲染等UI细节。

效果示意:监控面板初始状态所有设备标记为绿色(正常);当ID为3的设备上报异常后,其对应条目将实时变为红色(异常)。 图片

实现步骤

前端实现 (Vue + WebSocket)

前端负责创建 WebSocket 连接,监听后端推送的消息,并实时更新对应设备的状态。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>实时监控</title>
    </head>
    <style>
        .item {
            display: flex;
            border-bottom: 1px solid #000000;
            justify-content: space-between;
            width: 30%;
            line-height: 50px;
            height: 50px;
        }
        .item span:nth-child(2){
            margin-right: 10px;
            margin-top: 15px;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background: #55ff00;
        }
        .nowI {
            background: #ff0000!important;
        }
    </style>
    <body>
        <div id="app">
            <div v-for="item in list" class="item">
                <span>{{item.id}}.{{item.name}}</span>
                <span :class='item.state==-1?"nowI":""'></span>
            </div>
        </div>
    </body>

    <script type="text/javascript">
        var vm = new Vue({
            el: "#app",
            data: {
                list: [
                    { id: 1, name: '张三', state: 1 },
                    { id: 2, name: '李四', state: 1 },
                    { id: 3, name: '王五', state: 1 },
                    { id: 4, name: '韩梅梅', state: 1 },
                    { id: 5, name: '李磊', state: 1 },
                ]
            }
        })
        var webSocket = null;
        if ('WebSocket' in window) {
            // 创建WebSocket连接,连接路径中包含一个唯一用户ID
            webSocket = new WebSocket("ws://localhost:18801/webSocket/" + getUUID());
            // 连接成功回调
            webSocket.onopen = function() {
                console.log("WebSocket连接已建立");
                webSocket.send("客户端就绪"); // 可选:发送一条初始消息
            }
            // 接收到服务端消息
            webSocket.onmessage = function(msg) {
                // 处理消息:服务端推送的是异常设备的ID
                var serverMsg = msg.data;
                var abnormalId = parseInt(serverMsg); // 将字符串ID转为整数
                for (var i = 0; i < vm.list.length; i++) {
                    var item = vm.list[i];
                    if(item.id == abnormalId){
                        item.state = -1; // 将状态标记为异常
                        vm.list.splice(i, 1, item); // 触发Vue响应式更新
                        break;
                    }
                }
            };
            // 连接关闭回调
            webSocket.onclose = function() {
                console.log("WebSocket连接已关闭");
            };
            // 发生错误回调
            webSocket.onerror = function() {
                console.log("WebSocket连接发生错误");
            }
        } else {
            alert("当前浏览器不支持WebSocket!")
        }
        // 生成一个唯一标识符,用于WebSocket连接路径
        function getUUID() {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                var r = Math.random() * 16 | 0,
                    v = c == 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            });
        }
    </script>
</html>

后端实现 (SpringBoot)

后端项目结构如下,核心是配置WebSocket服务端和提供触发推送的HTTP接口。 图片

1. 创建SpringBoot工程 在创建项目时,引入 Spring WebWebSocket 依赖。 图片

2. 配置 application.yml 设置服务端口和一个简单的密码(用于接口鉴权,示例中简化处理)。

server:
  port: 18801

mySocket:
  myPwd: jae_123

3. 创建 WebSocket 配置类 启用WebSocket服务端支持。

@Configuration
public class WebSocketConfig {
    /**
     * 注入ServerEndpointExporter,自动注册使用@ServerEndpoint声明的WebSocket端点
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

4. 创建 WebSocket 服务端处理类 这是WebSocket的核心,处理连接、消息推送等生命周期事件。使用@ServerEndpoint注解定义连接端点。

/**
 * WebSocket服务端
 * @ServerEndpoint("/webSocket/{uid}") 前端通过此URI与后端建立连接
 */
@ServerEndpoint("/webSocket/{uid}")
@Component
public class WebSocketServer {
    private static Logger log = LoggerFactory.getLogger(WebSocketServer.class);
    // 记录当前在线连接数(线程安全)
    private static final AtomicInteger onlineNum = new AtomicInteger(0);
    // 存放每个客户端会话Session的线程安全集合
    private static CopyOnWriteArraySet<Session> sessionPools = new CopyOnWriteArraySet<Session>();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "uid") String uid){
        sessionPools.add(session);
        onlineNum.incrementAndGet();
        log.info(uid + "加入webSocket!当前在线人数为" + onlineNum);
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        sessionPools.remove(session);
        int cnt = onlineNum.decrementAndGet();
        log.info("有连接关闭,当前连接数为:{}", cnt);
    }

    /**
     * 向指定客户端发送消息
     */
    public void sendMessage(Session session, String message) throws IOException {
        if(session != null){
            synchronized (session) {
                session.getBasicRemote().sendText(message);
            }
        }
    }

    /**
     * 群发消息(广播)给所有已连接的客户端
     */
    public void broadCastInfo(String message) throws IOException {
        for (Session session : sessionPools) {
            if(session.isOpen()){
                sendMessage(session, message);
            }
        }
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable throwable){
        log.error("WebSocket发生错误");
        throwable.printStackTrace();
    }
}

5. 创建 HTTP 控制器,用于接收异常上报并触发WebSocket推送 该控制器提供一个模拟的“设备异常上报”接口,验证通过后,调用WebSocket服务进行广播。

@RestController
@RequestMapping("/open/socket")
public class WebSocketController {
    @Value("${mySocket.myPwd}")
    public String myPwd;
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 模拟设备异常上报接口
     * @param id  发生异常的设备ID
     * @param pwd 密码(实际开发中需加密传输和校验)
     * @throws IOException
     */
    @PostMapping(value = "/onReceive")
    public void onReceive(String id, String pwd) throws IOException {
        // 简单的密码校验(示例用途,生产环境需强化安全)
        if(pwd.equals(myPwd)){
            // 校验通过,向所有监控端广播异常设备ID
            webSocketServer.broadCastInfo(id);
        }
    }
}

功能测试

  1. 启动后端服务:运行SpringBoot应用。
  2. 打开前端页面:在浏览器中打开前端HTML文件,控制台应输出“WebSocket连接已建立”。 图片
  3. 查看初始状态:页面加载后,所有设备状态为绿色(正常)。 图片
  4. 模拟异常上报:使用 Postman 等API测试工具,调用后端 POST /open/socket/onReceive 接口,参数 id=3&pwd=jae_123图片
  5. 观察实时更新:调用接口后,前端页面无需刷新,ID为3的“王五”条目状态灯实时变为红色。 图片

至此,一个基于 SpringBoot 和 WebSocket 的简易实时异常监控系统就实现了。这套方案可以扩展应用于多种需要服务端主动推送实时数据的场景,如在线客服、实时报表、物联网监控等。在涉及 Java 后端和 前端框架 协同开发时,WebSocket 是构建高效实时功能的强有力工具,利用 Postman 等工具进行接口测试能有效验证业务逻辑。




上一篇:Btop系统监控高阶实战:12个运维提效与自定义技巧
下一篇:Quarkdown开源Markdown编辑器实战:支持编程逻辑与PDF/PPT多格式生成
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-7 21:48 , Processed in 0.103737 second(s), 37 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表