SpringBoot+WebSocket real-time monitoring exception

Write in front

This exception is not another exception. The exception mentioned in the title is a business exception.

Recently, I made a demand for fire equipment inspection. If any abnormality is found in the inspection, submit it through the mobile terminal, and obtain the information and location of the equipment in real time on the background real-time monitoring page, and then arrange employees to deal with it.

Because the server needs to actively send messages to the client, it is easy to think of using WebSocket to realize this function.

Websocket will not be introduced. The link is as follows: https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket

The front end is slightly complex. You need to use the mouse to trace points on a position distribution map, locate various devices and render according to different screen sizes. This paper will not introduce it, but simply use page style to render the effect.

Green represents normal and red represents abnormal

The expected effect is that before receiving the request, the exception is submitted by - > the king with id 3, and the king with id 3 turns red

realization:

front end:

Direct paste code

  1 <!DOCTYPE html>
  2 <html>
  3     <head>
  4         <meta charset="utf-8" />
  5         <title>Real time monitoring</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         
 17         .item span:nth-child(2){
 18             margin-right: 10px;
 19             margin-top: 15px;
 20             width: 20px;
 21             height: 20px;
 22             border-radius: 50%;
 23             background: #55ff00;
 24         }
 25         .nowI{
 26             background: #ff0000 !important;
 27         }
 28     </style>
 29     <body>
 30         <div id="app">
 31             <div v-for="item in list" class="item">
 32                 <span>{{item.id}}.{{item.name}}</span>
 33                 <span :class='item.state==-1?"nowI":""'></span>
 34             </div>
 35         </div>
 36     </body>
 37     <script src="./js/vue.min.js"></script>
 38     <script type="text/javascript">
 39         var vm = new Vue({
 40             el: "#app",
 41             data: {
 42                 list: [{
 43                         id: 1,
 44                         name: 'Zhang San',
 45                         state: 1
 46                     },
 47                     {
 48                         id: 2,
 49                         name: 'Li Si',
 50                         state: 1
 51                     },
 52                     {
 53                         id: 3,
 54                         name: 'Wang Wu',
 55                         state: 1
 56                     },
 57                     {
 58                         id: 4,
 59                         name: 'Mei Mei Han',
 60                         state: 1
 61                     },
 62                     {
 63                         id: 5,
 64                         name: 'Li Lei',
 65                         state: 1
 66                     },
 67                 ]
 68             }
 69         })
 70 
 71         var webSocket = null;
 72         if ('WebSocket' in window) {
 73             //Create WebSocket object
 74             webSocket = new WebSocket("ws://localhost:18801/webSocket/" + getUUID());
 75 
 76             //Connection succeeded
 77             webSocket.onopen = function() {    
 78                 console.log("Connected");
 79                 webSocket.send("Message sending test")
 80             }
 81             //Message received
 82             webSocket.onmessage = function(msg) {    
 83                 //Processing messages
 84                 var serverMsg = msg.data;
 85                 var t_id = parseInt(serverMsg)    //The ID and string of the message sent from the server must be converted into int type for comparison
 86                 for (var i = 0; i < vm.list.length; i++) {
 87                     var item = vm.list[i];
 88                     if(item.id == t_id){
 89                         item.state = -1;
 90                         vm.list.splice(i,1,item)
 91                         break;
 92                     }
 93                 }
 94             };
 95 
 96             //Close event
 97             webSocket.onclose = function() {
 98                 console.log("websocket Closed");
 99             };
100             //An error event occurred
101             webSocket.onerror = function() {
102                 console.log("websocket An error has occurred");
103             }
104         } else {
105             alert("Unfortunately, your browser does not support WebSocket!")
106         }
107 
108         function getUUID() {    //Get unique UUID
109             return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
110 
111                 var r = Math.random() * 16 | 0,
112                     v = c == 'x' ? r : (r & 0x3 | 0x8);
113                 return v.toString(16);
114             });
115         }
116     </script>
117 </html>

Back end:

The project structure is like this. There are key comments in the following code, so the description will not be repeated

1. Create a new SpringBoot project and select web and WebSocket dependencies

2. Configure application yml

  1 <!DOCTYPE html>
  2 <html>
  3     <head>
  4         <meta charset="utf-8" />
  5         <title>Real time monitoring</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         
 17         .item span:nth-child(2){
 18             margin-right: 10px;
 19             margin-top: 15px;
 20             width: 20px;
 21             height: 20px;
 22             border-radius: 50%;
 23             background: #55ff00;
 24         }
 25         .nowI{
 26             background: #ff0000 !important;
 27         }
 28     </style>
 29     <body>
 30         <div id="app">
 31             <div v-for="item in list" class="item">
 32                 <span>{{item.id}}.{{item.name}}</span>
 33                 <span :class='item.state==-1?"nowI":""'></span>
 34             </div>
 35         </div>
 36     </body>
 37     <script src="./js/vue.min.js"></script>
 38     <script type="text/javascript">
 39         var vm = new Vue({
 40             el: "#app",
 41             data: {
 42                 list: [{
 43                         id: 1,
 44                         name: 'Zhang San',
 45                         state: 1
 46                     },
 47                     {
 48                         id: 2,
 49                         name: 'Li Si',
 50                         state: 1
 51                     },
 52                     {
 53                         id: 3,
 54                         name: 'Wang Wu',
 55                         state: 1
 56                     },
 57                     {
 58                         id: 4,
 59                         name: 'Mei Mei Han',
 60                         state: 1
 61                     },
 62                     {
 63                         id: 5,
 64                         name: 'Li Lei',
 65                         state: 1
 66                     },
 67                 ]
 68             }
 69         })
 70 
 71         var webSocket = null;
 72         if ('WebSocket' in window) {
 73             //Create WebSocket object
 74             webSocket = new WebSocket("ws://localhost:18801/webSocket/" + getUUID());
 75 
 76             //Connection succeeded
 77             webSocket.onopen = function() {    
 78                 console.log("Connected");
 79                 webSocket.send("Message sending test")
 80             }
 81             //Message received
 82             webSocket.onmessage = function(msg) {    
 83                 //Processing messages
 84                 var serverMsg = msg.data;
 85                 var t_id = parseInt(serverMsg)    //The ID and string of the message sent from the server must be converted into int type for comparison
 86                 for (var i = 0; i < vm.list.length; i++) {
 87                     var item = vm.list[i];
 88                     if(item.id == t_id){
 89                         item.state = -1;
 90                         vm.list.splice(i,1,item)
 91                         break;
 92                     }
 93                 }
 94             };
 95 
 96             //Close event
 97             webSocket.onclose = function() {
 98                 console.log("websocket Closed");
 99             };
100             //An error event occurred
101             webSocket.onerror = function() {
102                 console.log("websocket An error has occurred");
103             }
104         } else {
105             alert("Unfortunately, your browser does not support WebSocket!")
106         }
107 
108         function getUUID() {    //Get unique UUID
109             return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
110 
111                 var r = Math.random() * 16 | 0,
112                     v = c == 'x' ? r : (r & 0x3 | 0x8);
113                 return v.toString(16);
114             });
115         }
116     </script>
117 </html>

3. WebSocketConfig configuration class

 1 @Configuration
 2 public class WebSocketConfig {
 3 
 4     /**
 5      * Inject a ServerEndpointExporter, and the Bean will automatically register the websocket endpoint declared with the @ ServerEndpoint annotation
 6      */
 7     @Bean
 8     public ServerEndpointExporter serverEndpointExporter(){
 9         return new ServerEndpointExporter();
10     }
11 }

4. WebSocketServer class is used to interact between server and client

 1 /**
 2  * @author jae
 3  * @ServerEndpoint("/webSocket/{uid}") The front end links to the back end through this URI
 4  */
 5 
 6 @ServerEndpoint("/webSocket/{uid}")
 7 @Component
 8 public class WebSocketServer {
 9 
10     private static Logger log = LoggerFactory.getLogger(WebSocketServer.class);
11 
12     //Static variable, used to record the current number of online connections. It should be designed to be thread safe.
13     private static final AtomicInteger onlineNum = new AtomicInteger(0);
14 
15     //The thread safe Set of the concurrent package is used to store the WebSocketServer object corresponding to each client.
16     private static CopyOnWriteArraySet<Session> sessionPools = new CopyOnWriteArraySet<Session>();
17 
18     /**
19      * There are clients connected successfully
20      */
21     @OnOpen
22     public void onOpen(Session session, @PathParam(value = "uid") String uid){
23         sessionPools.add(session);
24         onlineNum.incrementAndGet();
25         log.info(uid + "join webSocket!The current number is" + onlineNum);
26     }
27 
28     /**
29      * Method called for connection closure
30      */
31     @OnClose
32     public void onClose(Session session) {
33         sessionPools.remove(session);
34         int cnt = onlineNum.decrementAndGet();
35         log.info("There are connections closed. The current number of connections is:{}", cnt);
36     }
37 
38     /**
39      * send message
40      */
41     public void sendMessage(Session session, String message) throws IOException {
42         if(session != null){
43             synchronized (session) {
44                 session.getBasicRemote().sendText(message);
45             }
46         }
47     }
48 
49     /**
50      * Mass messaging
51      */
52     public void broadCastInfo(String message) throws IOException {
53         for (Session session : sessionPools) {
54             if(session.isOpen()){
55                 sendMessage(session, message);
56             }
57         }
58     }
59 
60     /**
61      * An error occurred
62      */
63     @OnError
64     public void onError(Session session, Throwable throwable){
65         log.error("An error occurred");
66         throwable.printStackTrace();
67     }
68 
69 }

5. WebSocketController class, used for interface testing

 1 @RestController
 2 @RequestMapping("/open/socket")
 3 public class WebSocketController {
 4 
 5     @Value("${mySocket.myPwd}")
 6     public String myPwd;
 7 
 8     @Autowired
 9     private WebSocketServer webSocketServer;
10 
11     /**
12      * Mobile client request interface
13      * @param id    Device ID with exception
14      * @param pwd   Password (remember to encrypt in actual development)
15      * @throws IOException
16      */
17     @PostMapping(value = "/onReceive")
18     public void onReceive(String id,String pwd) throws IOException {
19         if(pwd.equals(myPwd)){  //If the password verification is consistent (for example, there is also a verification of password encryption in the actual development), mass sending will be carried out
20             webSocketServer.broadCastInfo(id);
21         }
22     }
23 
24 }

test

1. Open the front page to connect to WebSocket

Console output, connection successful

2. Because it is analog data, all display is normal, and there is no exception. The page is rendered when submitting

3. Next, we submit an exception using the interface testing tool Postman

Note the state change of the data with id 3

We can see that the status of Wang Wu with id 3 has become abnormal, and the real-time communication is successful.

reference resources: https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket

last

There is a demand for real-time monitoring in this aspect. You can refer to it.

Shortcomings are welcome to point out. If you find it useful, just point out a recommendation!

Keywords: Java Programming Algorithm architecture Singleton pattern

Added by AdB on Tue, 04 Jan 2022 22:01:11 +0200