Backend Development 21 min read

Real-Time Device Monitoring with SpringBoot WebSocket and Vue

This article demonstrates how to build a real‑time fire‑equipment inspection system using SpringBoot WebSocket on the backend and a Vue‑based frontend, covering project setup, WebSocket configuration, server‑client communication, and testing with code examples.

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

The author describes a requirement for fire‑equipment inspection where abnormal device status reported from a mobile client must be pushed to a backend and displayed instantly on a monitoring page, prompting staff to handle the issue.

Because the server needs to actively push messages to the client, WebSocket is chosen as the communication protocol.

Implementation

Frontend

The frontend is a simple Vue page that renders a list of devices and changes the color of a device to red when its state becomes abnormal. The HTML and CSS are defined directly in the page.

1 <!DOCTYPE html>
2 <html>
3   <head>
4     <meta charset="utf-8" />
5     <title>实时监控</title>
6 </head>
7 <style>
8 .item {
9   display: flex;
10   border-bottom: 1px solid #000000;
11   justify-content: space-between;
12   width: 30%;
13   line-height: 50px;
14   height: 50px;
15 }
16 .item span:nth-child(2){
17   margin-right: 10px;
18   margin-top: 15px;
19   width: 20px;
20   height: 20px;
21   border-radius: 50%;
22   background: #55ff00;
23 }
24 .nowI{
25   background: #ff0000 !important;
26 }
27 </style>
28 <body>
29   <div id="app">
30     <div v-for="item in list" class="item">
31       <span>{{item.id}}.{{item.name}}</span>
32       <span :class='item.state==-1?"nowI":""'></span>
33     </div>
34   </div>
35 </body>
36 <script src="./js/vue.min.js"></script>
37 <script type="text/javascript">
38   var vm = new Vue({
39     el: "#app",
40     data: {
41       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}]
42   });
43   var webSocket = null;
44   if ('WebSocket' in window) {
45     webSocket = new WebSocket("ws://localhost:18801/webSocket/" + getUUID());
46     webSocket.onopen = function() { console.log("已连接"); webSocket.send("消息发送测试"); };
47     webSocket.onmessage = function(msg) {
48       var serverMsg = msg.data;
49       var t_id = parseInt(serverMsg);
50       for (var i = 0; i < vm.list.length; i++) {
51         var item = vm.list[i];
52         if(item.id == t_id){ item.state = -1; vm.list.splice(i,1,item); break; }
53       }
54     };
55   } else { alert("很遗憾,您的浏览器不支持WebSocket!"); }
56   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); }); }

Backend

The backend is a SpringBoot project with WebSocket dependencies. The application.yml sets the server port to 18801 and defines a simple password for demonstration.

#端口
server:
  port: 18801

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

A WebSocketConfig class registers ServerEndpointExporter so that beans annotated with @ServerEndpoint are automatically detected.

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

The core server endpoint is WebSocketServer , which manages connections, broadcasts messages, and handles errors. It uses a thread‑safe CopyOnWriteArraySet<Session> to store active sessions and an AtomicInteger to track online count.

@ServerEndpoint("/webSocket/{uid}")
@Component
public class WebSocketServer {
    private static Logger log = LoggerFactory.getLogger(WebSocketServer.class);
    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);
    }

    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        // handle incoming messages if needed
    }

    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 simple WebSocketController exposes a POST endpoint /open/socket/onReceive that receives an equipment ID and a password. If the password matches the configured value, the controller triggers a broadcast to all connected WebSocket clients, causing the frontend to mark the corresponding device as abnormal.

@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

1. Open the frontend page; the console shows "已连接" indicating a successful WebSocket connection.

2. Initially all devices appear normal (green).

3. Use a tool such as Postman to POST to /open/socket/onReceive with id=3 and the correct password. The server broadcasts the ID, the frontend receives it, and the item with ID 3 turns red, confirming real‑time communication.

Conclusion

The example provides a complete end‑to‑end demonstration of real‑time monitoring using SpringBoot WebSocket on the backend and Vue on the frontend, which can be adapted to similar inspection or alerting scenarios in production environments.

BackendVueReal-time MonitoringWebSocketSpringBoot
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

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.