zoukankan      html  css  js  c++  java
  • springboot 整合websocket实现消息推送(nginx、vue)

    最近需要一个动态图表的功能,如下图。

    这种实现需要实时推送数据上来,那一般有两种方法

    方法一:前端写个定时器,不断轮询后台即可。这当然是很low的,请求太多很不友好,果断抛弃

    方法二:使用websocket,废话不多说直接上代码

    springboot 整合websocket有两种方法,这里先记录原始方法:

    添加webSocket插件

         <!--websocket-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-websocket</artifactId>
            </dependency>

    WebSocketConfig配置

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.config.annotation.EnableWebSocket;
    import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    //注意注解
    @EnableWebSocket
    @Configuration
    public class WebSocketConfig {
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    }

    然后写个webSocket工具类

    import org.springframework.stereotype.Controller;
    import javax.websocket.OnClose;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.PathParam;
    import javax.websocket.server.ServerEndpoint;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.CopyOnWriteArraySet;
    //注意是controller注解
    @Controller
    @ServerEndpoint("/websocket/{tableId}")
    public class WebSocket {
        private Session session;
    public static CopyOnWriteArraySet<WebSocket> webSockets =new CopyOnWriteArraySet<>();
        private static Map<String,Session> sessionPool = new HashMap<String,Session>();
    
        @OnOpen
        public void onOpen(Session session, @PathParam(value="tableId")String code) {
            this.session = session;
            webSockets.add(this);
            sessionPool.put(code, session);
           // Constants.WEBSOCKET = true;//定义常量  是否开启websocket连接
            System.out.println("【websocket消息】有新的连接,总数为:"+webSockets.size());
        }
    
        @OnClose
        public void onClose() {
            webSockets.remove(this);
            //Constants.WEBSOCKET = false;
            System.out.println("【websocket消息】连接断开,总数为:"+webSockets.size());
        }
    
        @OnMessage
        public void onMessage(String message) {
            System.out.println("【websocket消息】收到客户端消息:"+message);
        }
    
        // 此为广播消息
        public void sendAllMessage(String message) {
            for(WebSocket webSocket : webSockets) {
                System.out.println("【websocket消息】广播消息:"+message);
                try {
                    webSocket.session.getAsyncRemote().sendText(message);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        // 此为单点消息
        public void sendOneMessage(String code, String message) {
            Session session = sessionPool.get(code);
            System.out.println(code);
            /*在发送数据之前先确认 session是否已经打开 使用session.isOpen() 为true 则发送消息
             * 不然会报错:The WebSocket session [0] has been closed and no method (apart from close()) may be called on a closed session */
            if (session != null && session.isOpen()) {
                try {
                    session.getAsyncRemote().sendText(message);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    简单的已经可以使用的,注意如果后台有用shiro权限框架的注意要开放接口

    测试

    下面介绍一种在线测试工具 http://ws.douqq.com/

    如果项目是前后端分离的,需要nginx进行请求转发的需要在nginx的配置文件里添加如下配置:红色字体部分

    主要是把websocket的请求和http请求区分开

    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        sendfile        on;
        keepalive_timeout  65;
        
         map $http_upgrade $connection_upgrade { 
             default upgrade;
             '' close;
            }
    
        server {
            listen       888;
            server_name  localhost;
    
        location ~/websocket/ {
            proxy_pass http://127.0.0.1:8089;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For     
            $proxy_add_x_forwarded_for;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
           }
               
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
        }
    }    

    这个时候接口换成nginx监听接口即可:

    待这些测试完之后在页面new一个websocket即可,我这里用的vue

    
    
    created(){
        this.initWebSocket();
      },
    destroyed() {
        this.websocketclose();
      },
    initWebSocket: function () {
          //debugger;
          // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https   key你自定义的key
          //var host = window.location.host
          this.websock = new WebSocket("ws://47.106.172.176:888/websocket/123");
          this.websock.onopen = this.websocketonopen;
          this.websock.onerror = this.websocketonerror;
          this.websock.onmessage = this.websocketonmessage;
          this.websock.onclose = this.websocketclose;
          console.log(this.websock);
          //this.websock.send("您好啊");
        },
        websocketonopen: function () {
        },
        websocketonerror: function (e) {
        },
        websocketonmessage: function (e) {//JSON.parse(e.data); //这个是收到后端主动推送的值
        },
        websocketclose: function (e) {
        },

    如果想要后端不断推送数据上来,可以写个定时任务:

    @Component
    public class ScheduledTask {
       
        @Autowired
        private WebSocket webSocket;
        //添加定时任务
        //@Scheduled(cron = "0/5 * * * * ?")
        @Scheduled(fixedRate=2000)
        public void sendMessage() {
            System.out.println("定时发送数据");
            //webSocket.sendAllMessage(JSON.toJSONString("str"));
        //调用websocket推送消息
    webSocket.sendOneMessage("1","str"); } }
  • 相关阅读:
    [洛谷P1507]NASA的食物计划 以及 对背包问题的整理
    [洛谷P3811]【模板】乘法逆元
    56级信息奥赛12学子汇总
    [洛谷U63006]导函数最小系数
    [洛谷U62364]三次函数极值
    [洛谷U62358]求导函数
    Nagios 请检查HTTP服务器关于该CGI的访问权限设置
    安装Cacti-plugin
    解压安装Cacti在apache中的补充
    64位操作系统下IIS报“试图加载格式不正确的程序”错误
  • 原文地址:https://www.cnblogs.com/lwx521/p/14086949.html
Copyright © 2011-2022 走看看