Backend Development 10 min read

Real-Time Device Monitoring with WebSocket Using Vue and SpringBoot

This article demonstrates how to build a real‑time device monitoring system by using WebSocket for server‑client communication, Vue for the front‑end display, and SpringBoot for the back‑end service, covering code examples, configuration, and testing steps.

Architect
Architect
Architect
Real-Time Device Monitoring with WebSocket Using Vue and SpringBoot

The article describes a scenario where fire‑equipment inspection results are submitted via a mobile client, and the backend pushes the abnormal device information to a real‑time monitoring page. Because the server needs to actively send messages to the client, WebSocket is chosen as the communication method.

Front‑end implementation – A simple Vue page lists devices with colored indicators (green for normal, red for abnormal). The HTML and CSS are provided, followed by JavaScript that creates a Vue instance, opens a WebSocket connection, handles incoming messages, and updates the device state.

<!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 src="./js/vue.min.js"></script>
    <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 = new WebSocket("ws://localhost:18801/webSocket/" + getUUID());
            webSocket.onopen = function(){
                console.log("已连接");
                webSocket.send("消息发送测试")
            }
            webSocket.onmessage = function(msg){
                var serverMsg = msg.data;
                var t_id = parseInt(serverMsg);
                for (var i = 0; i < vm.list.length; i++) {
                    var item = vm.list[i];
                    if(item.id == t_id){
                        item.state = -1;
                        vm.list.splice(i,1,item)
                        break;
                    }
                }
            };
            webSocket.onclose = function(){
                console.log("websocket已关闭");
            };
            webSocket.onerror = function(){
                console.log("websocket发生了错误");
            }
        } else {
            alert("很遗憾,您的浏览器不支持WebSocket!")
        }
        function getUUID(){    //获取唯一的UUID
            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>

Back‑end implementation – A SpringBoot project is created with WebSocket dependencies. The application.yml configures the server port and a simple password for validation.

#端口
server:
  port: 18801

#密码,因为接口不需要权限,所以加了个密码做校验
mySocket:
  myPwd: jae_123

The WebSocketConfig class registers a ServerEndpointExporter bean, enabling the use of @ServerEndpoint annotations.

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

The WebSocketServer class defines lifecycle callbacks ( @OnOpen , @OnClose , @OnMessage , @OnError ) and provides methods for sending messages to a single session or broadcasting to all connected sessions.

@ServerEndpoint("/webSocket/{uid}")
@Component
public class WebSocketServer {
    private static final AtomicInteger onlineNum = new AtomicInteger(0);
    private static CopyOnWriteArraySet
sessionPools = new CopyOnWriteArraySet<>();
    @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("发生错误");
        throwable.printStackTrace();
    }
}

A WebSocketController exposes a REST endpoint /open/socket/onReceive that receives an abnormal device ID and a password; after password verification it broadcasts the ID to all connected clients.

@RestController
@RequestMapping("/open/socket")
public class WebSocketController {
    @Value("${mySocket.myPwd}")
    public String myPwd;
    @Autowired
    private WebSocketServer webSocketServer;
    @PostMapping(value = "/onReceive")
    public void onReceive(String id,String pwd) throws IOException {
        if(pwd.equals(myPwd)){
            webSocketServer.broadCastInfo(id);
        }
    }
}

Testing – Open the front‑end page, observe the WebSocket connection log, then use Postman to POST an abnormal device ID (e.g., id=3). The corresponding device entry turns red, confirming that the real‑time push works.

Finally, the article notes that the described approach can be referenced for similar real‑time monitoring needs in production.

BackendFrontendReal-time MonitoringWebSocketVue.jsSpringBoot
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.