• [WebSocket长连接]SpringBoot2.0集成WebSocket,实现后台向前端推送信息


    感谢作者,支持原创: https://blog.csdn.net/moshowgame/article/details/80275084

    什么是WebSocket?

    WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。

    为什么需要 WebSocket?

    初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?

    • 答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起,HTTP 协议做不到服务器主动向客户端推送信息。

    举例来说,我们想要查询当前的排队情况,只能是页面轮询向服务器发出请求,服务器返回查询结果。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此WebSocket 就是这样发明的。

     

    Maven依赖

     1         <!--springboot的高级组件会自动引用基础的组件-->
     2         <!--,像spring-boot-starter-websocket就引入了spring-boot-starter-web和spring-boot-starter,-->
     3         <!--所以不要重复引入。-->
     4         <!--JavaEE标准-->
     5         <dependency>
     6             <groupId>javax</groupId>
     7             <artifactId>javaee-api</artifactId>
     8             <scope>provided</scope>
     9         </dependency>
    10         <!--websocket-->
    11         <dependency>
    12             <groupId>org.springframework.boot</groupId>
    13             <artifactId>spring-boot-starter-websocket</artifactId>
    14         </dependency>

    WebSocket配置类

     1 package com.zr.demo.config;
     2 
     3 import org.springframework.context.annotation.Bean;
     4 import org.springframework.context.annotation.Configuration;
     5 import org.springframework.web.socket.server.standard.ServerEndpointExporter;
     6 
     7 /**
     8  * @Author: Hujh
     9  * @Date: 2019/7/16 11:10
    10  * @Description: WebSocket配置类
    11  */
    12 @Configuration
    13 public class WebSocketConfig {
    14 
    15     /*使用@ServerEndpoint创立websocket endpoint*/
    16     @Bean
    17     public ServerEndpointExporter serverEndpointExporter() {
    18         return new ServerEndpointExporter();
    19     }
    20 }

    WebSocketServer

    因为WebSocket是类似客户端服务端的形式(采用ws协议),那么这里的WebSocketServer其实就相当于一个ws协议的Controller直接@ServerEndpoint("/websocket")@Component启用即可,然后在里面实现@OnOpen,@onClose,@onMessage等方法

      1 package com.zr.demo.socket;
      2 
      3 import org.springframework.stereotype.Component;
      4 
      5 import javax.websocket.OnClose;
      6 import javax.websocket.OnMessage;
      7 import javax.websocket.OnOpen;
      8 import javax.websocket.Session;
      9 import javax.websocket.server.ServerEndpoint;
     10 import java.io.IOException;
     11 import java.util.concurrent.CopyOnWriteArraySet;
     12 
     13 /**
     14  * @Author: Hujh
     15  * @Date: 2019/7/16 11:13
     16  * @Description: webSocket实现类
     17  */
     18 @ServerEndpoint(value = "/webSocket")
     19 @Component
     20 public class WebSocket {
     21     //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
     22     private static int onlineCount = 0;
     23 
     24     //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
     25     private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<WebSocket>();
     26 
     27     //与某个客户端的连接会话,需要通过它来给客户端发送数据
     28     private Session session;
     29 
     30     /**
     31      * 连接建立成功调用的方法
     32      */
     33     @OnOpen
     34     public void onOpen(Session session) {
     35         this.session = session;   //加入set中
     36         webSocketSet.add(this);
     37         addOnlineCount();  //在线数加1
     38         System.out.println("有新连接加入!当前在线人数为:" + getOnlineCount());
     39         try {
     40             sendMessage("连接成功");
     41         } catch (IOException e) {
     42             System.out.println("IO异常");
     43         }
     44     }
     45 
     46     /**
     47      * 连接关闭调用的方法
     48      */
     49     @OnClose
     50     public void onClose() {
     51         webSocketSet.remove(this);  //从set中删除
     52         subOnlineCount();           //在线数减1
     53         System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
     54     }
     55 
     56     /**
     57      * 收到客户端消息后调用的方法
     58      * @param message 客户端发送过来的消息
     59      */
     60     @OnMessage
     61     public void onMessage(String message, Session session) {
     62         System.out.println("来自客户端的消息:" + message);
     63 
     64         //群发消息
     65         for (WebSocket item : webSocketSet) {
     66             try {
     67                 item.sendMessage(message);
     68             } catch (IOException e) {
     69                 e.printStackTrace();
     70             }
     71         }
     72     }
     73 
     74     /**
     75      * 发生错误时调用
     76      @OnError
     77      */
     78      public void onError(Session session, Throwable error) {
     79      System.out.println("发生错误");
     80      error.printStackTrace();
     81      }
     82 
     83     /*
     84      * @Title: sendMessage
     85      * @Author : Hujh
     86      * @Date: 2019/7/17 10:52
     87      * @Description : 发送消息
     88      * @param : message
     89      * @Return : void
     90      */
     91      public void sendMessage(String message) throws IOException {
     92         this.session.getBasicRemote().sendText(message);
     93      //this.session.getAsyncRemote().sendText(message);
     94      }
     95 
     96 
     97      /*
     98       * @Title: sendInfo
     99       * @Author : Hujh
    100       * @Date: 2019/7/17 10:52
    101       * @Description : 群发自定义消息
    102       * @param : message
    103       * @Return : void
    104       */
    105     public static void sendInfo(String message) throws IOException {
    106         for (WebSocket item : webSocketSet) {
    107             try {
    108                 item.sendMessage(message);
    109             } catch (IOException e) {
    110                 continue;
    111             }
    112         }
    113     }
    114 
    115     /*
    116      * @Title: getOnlineCount
    117      * @Author : Hujh
    118      * @Date: 2019/7/17 10:51
    119      * @Description : 获得当前在线人数
    120      * @param :
    121      * @Return : int
    122      */
    123     public static synchronized int getOnlineCount() {
    124         return onlineCount;
    125     }
    126 
    127     /*
    128      * @Title: addOnlineCount
    129      * @Author : Hujh
    130      * @Date: 2019/7/17 10:51
    131      * @Description : 在线人数+1
    132      * @param :
    133      * @Return : void
    134      */
    135     public static synchronized void addOnlineCount() {
    136         WebSocket.onlineCount++;
    137     }
    138 
    139     /*
    140      * @Title: subOnlineCount
    141      * @Author : Hujh
    142      * @Date: 2019/7/17 10:52
    143      * @Description :在线人数-1
    144      * @param :
    145      * @Return : void
    146      */
    147     public static synchronized void subOnlineCount() {
    148         WebSocket.onlineCount--;
    149     }
    150 
    151 }

    消息推送

    至于推送新信息,可以再自己的Controller写个方法调用WebSocket.sendInfo();

     1 package com.zr.demo.controller;
     2 
     3 import com.zr.demo.socket.WebSocket;
     4 import org.springframework.beans.factory.annotation.Autowired;
     5 import org.springframework.web.bind.annotation.RequestMapping;
     6 import org.springframework.web.bind.annotation.RequestParam;
     7 import org.springframework.web.bind.annotation.RestController;
     8 
     9 /**
    10  * @Author: Hujh
    11  * @Date: 2019/7/19 15:40
    12  * @Description: 消息发送控制器
    13  */
    14 @RestController
    15 public class SendMessageController {
    16 
    17     @Autowired
    18     private WebSocket webSocket;
    19 
    20     @RequestMapping("sendInfo")
    21     public String sendInfo(@RequestParam String msg) {
    22         try {
    23             webSocket.sendInfo(msg);
    24         } catch (Exception e) {
    25             e.printStackTrace();
    26             return "信息发送异常!";
    27         }
    28 
    29         return "发送成功~";
    30     }
    31 
    32 }

    页面代码

     1 <!DOCTYPE HTML>
     2 <html>
     3 <head>
     4     <title>WebSocket</title>
     5 </head>
     6 
     7 <body>
     8 <div style=" 800px;height: 100%; margin: 0px auto;">
     9     <span style="color: coral; font-size: 22px;"> Welcome WebSocket</span><br/><br/>
    10     <div id="message">
    11     </div>
    12 </div>
    13 </body>
    14 
    15 <script type="text/javascript">
    16     var websocket = null;
    17     //判断当前浏览器是否支持WebSocket
    18     if('WebSocket' in window){
    19         websocket = new WebSocket("ws://localhost:8082/webSocket");
    20     }else{
    21         alert('连接失败!!')
    22     }
    23 
    24     //连接发生错误的回调方法
    25     websocket.onerror = function(){
    26         setMessageInnerHTML("error");
    27     };
    28 
    29     //连接成功建立的回调方法
    30     websocket.onopen = function(event){
    31         setMessageInnerHTML("webSocket 连接成功~");
    32     }
    33 
    34     //接收到消息的回调方法
    35     websocket.onmessage = function(event){
    36         setMessageInnerHTML(event.data);
    37     }
    38 
    39     //连接关闭的回调方法
    40     websocket.onclose = function(){
    41         setMessageInnerHTML("close");
    42     }
    43 
    44     //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,
    45     // 防止连接还没断开就关闭窗口,server端会抛异常。
    46     window.onbeforeunload = function(){
    47         websocket.close();
    48     }
    49 
    50     //将消息显示在网页上
    51     function setMessageInnerHTML(innerHTML){
    52         document.getElementById('message').innerHTML += innerHTML + '<br/>';
    53     }
    54 
    55     //关闭连接
    56     function closeWebSocket(){
    57        websocket.close();
    58     }
    59 
    60   61 </script>
    62 </html>

    测试效果

    1.建立两个连接

    2.消息推送

     

     注:本文仅作为个人学习记录,不提供任何参考价值!

  • 相关阅读:
    集算器如何优化SQL计算(2)分组
    集算器如何优化SQL计算(1)动态列
    android DOM解析Xml
    ASP.NET 抓取网页内容
    抓取HTML网页数据
    [转]Android的网络与通信
    Android的三种网络通信方式
    Android通过onDraw实现在View中绘图操作
    Android Canvas类介绍
    DatabaseMetaData的用法(转)
  • 原文地址:https://www.cnblogs.com/hujunhui/p/11212454.html
Copyright © 2020-2023  润新知