SpringBoot+WebSocket实现简单的数据推送

问题背景

为什么要要用websocket呢?websocket相对于传统http协议有什么优势呢?

  • http协议有一个缺陷,就是通信只能由客户端发起,服务器返回数据,不能做到服务器主动向客户端推送。这就导致了一个弊端,假如我要获得服务器连续的状态变化,那么我只能每隔一段时间向服务器发起请求,也就是所谓的轮询,这就导致了大量的资源浪费。由此,websocket应运而生,来解决这一痛点。
  • websocket使用tcp连接保持全双工通信协议,服务器端比较容易实现;
  • 数据格式比较轻量,通信比较高效;
  • 既能发送文本,也能发送二进制数据,没有同源限制;
  • wbsocket响应报文与http不同,如下
SpringBoot WebSocket实现简单的数据推送

websocket响应报文

好了,简单的了解一下,我们来看看springboot websocket实现推送的过程,以下是个简单的demo。

搭建过程

  • 首先我们初始化一个spring boot项目,大家可以根据自己的习惯去官网下载或者用idea来生成,这里我不多说,主要的是引入websocket依赖,如下图;
SpringBoot WebSocket实现简单的数据推送

websocket依赖

  • 编写websocket配置类,这里直接new 一个ServerEndpointExporter就行了
@Component
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }}
  • 编写websocket推送服务端
@Component
@ServerEndpoint(value = "/websocket/logging")
public class LoggingWSServer {
    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingWSServer.class);
    private static Map<String, Session> sessionMap = new ConcurrentHashMap<>();
    private static Gson gson = new Gson();
    private static Map<String,Object> map = new ConcurrentHashMap<>();
    @OnOpen
    public void onOpen(Session session) {
      new Thread(() -> {		// 这里大家可以根据业务来优化,使用线程池等手段
            while(sessionMap.get(session.getId()) != null) {
                try {
                    List list = aaaServerService.findList();
                    if(session.isOpen()) {
                        send(session, gson.toJson(list));
                    }
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
    
    @OnClose
    public void onClose(Session session) {
        sessionMap.remove(session.getId());
        LOGGER.info("session断开连接:{}" , session.getId());
    }
    @OnMessage
    public void onMessage(String message,Session session) {
        LOGGER.info("收到客户端的消息:{}",message);
        map.put("ret",message);
        send(session,gson.toJson(map));
    }
    private void send(Session session, String toJson) {
        try {
            session.getBasicRemote().sendText(toJson);
        } catch (IOException e) {
            LOGGER.error("发送错误:{}",e.getMessage());
        }
    }
  
}

服务端api解释:

  • OnOpen:在这个端点连接时被调用;
  • OnClose:与OnOpen相反,连接断开时被调用
  • OnMessage:服务端收到客户端的信息时被调用
  • OnError:当然还有这个,上面没有列出,这是发送错误时被调用
  • 编写前端页面,这里只展示js
    //websocket对象
    var websocket = null;    //判断当前浏览器是否支持WebSocket    if (\'WebSocket\' in window) {
        //动态获取域名或ip        var hostname = window.location.hostname;        port = window.location.port;        websocket = new WebSocket("ws://" hostname ":"   port   "/websocket/logging");
    } else {
        console.error("不支持WebSocket");
    }    //连接发生错误的回调方法    websocket.onerror = function (e) {
        console.error("WebSocket连接发生错误"   e);
    };    //连接成功建立的回调方法    websocket.onopen = function () {
        console.log("WebSocket连接成功")
    };    //接收到消息的回调方法    websocket.onmessage = function (event) {
        console.log("数据是:", event.data );
        var data = JSON.parse(event.data);        if (data.push) {
            // 内容            var temp = template(\'tpl_data\',{data : data.push});
            console.log("模板=="   temp);
            document.getElementById("tb").innerHTML = temp;
        }        if(data.ret) {
            console.log(data.ret)
            alert(data.ret);        }    }    //发送消息    $(\'#send\').click(function () {
        websocket.send($(\'#sMsg\').val());
    });

前端页面注意

  • 编写的时候一定要注意一个地方,就是new WebSocket 的地址,一定要和服务端推送的那个地址相同,不然的话,这里接收不到推送过来的数据。
  • 另外,有些浏览器可能不支持websocket,也没关系,可以使用sockjs或者stomp.js,这是基于websocket的上层协议,大家可以自行去了解以下。不过要注意,sockjs 处理的url是http或者https,不在是以ws开头的。

内容出处:,

声明:本网站所收集的部分公开资料来源于互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时修改或删除。文章链接:http://www.yixao.com/procedure/11994.html

发表评论

登录后才能评论