zoukankan      html  css  js  c++  java
  • SpringBoot2.x服务器端主动推送技术

    一.服务端推送常用技术介绍

      服务端主流推送技术:websocket、SSE等

      1.客户端轮询:ajax定时拉取后台数据

        js   setInterval定时函数  +  ajax异步加载  定时向服务器发送请求

        服务器压力会较大

      2.服务端主动推送:websocket《推荐使用

        全双工即双向通讯,本质上是一个额外的TCP连接,建立和关闭时握手使用http协议,其他数据传输不使用http协议,更加复杂一些,适用于需要进行复杂双向数据通讯的场景,支持大部分主流浏览器。

        开发成本较高,适用性较好,适用于聊天功能等。

        WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

      客户端代码

    var websocket = null;
    //判断当前浏览器是否支持WebSocket
    if ('WebSocket' in window) {
    websocket = new WebSocket("ws://localhost:8080/WebSocketTest/websocket");
    }
    else {
    alert('当前浏览器 Not support websocket')
    }

    //连接发生错误的回调方法
    websocket.onerror = function () {
    setMessageInnerHTML("WebSocket连接发生错误");
    };

    //连接成功建立的回调方法
    websocket.onopen = function () {
    setMessageInnerHTML("WebSocket连接成功");
    }

    //接收到消息的回调方法
    websocket.onmessage = function (event) {
    setMessageInnerHTML(event.data);
    }

    //连接关闭的回调方法
    websocket.onclose = function () {
    setMessageInnerHTML("WebSocket连接关闭");
    }

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
    closeWebSocket();
    }

    //将消息显示在网页上
    function setMessageInnerHTML(innerHTML) {
    document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }

    //关闭WebSocket连接
    function closeWebSocket() {
    websocket.close();
    }

    //发送消息
    function send() {
    var message = document.getElementById('text').value;
    websocket.send(message);
    }

    服务端代码

    /**
    * websocket服务
    * @author like
    *
    */
    @ServerEndpoint("/websocket")
    public class WebsocketTest {

    private static int onlineCount=0;//记录当前在线人数


    //确保线程安全
    private static CopyOnWriteArraySet<WebsocketTest> webSocketSet=new CopyOnWriteArraySet<WebsocketTest>();

    private Session session;

    @OnOpen
    public void onOpen(Session session){
    this.session=session;
    webSocketSet.add(this);
    addOnlineCount();
    System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
    }

    @OnClose
    public void OnClose(){
    webSocketSet.remove(this); //从set中删除
    subOnlineCount(); //在线数减1
    System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
    }

    @OnMessage
    public void OnMessage(String message, Session session){
    System.out.println("来自客户端的消息:" + message);
    //群发消息
    for(WebsocketTest item: webSocketSet){
    try {
    item.sendMessage(message);
    } catch (IOException e) {
    e.printStackTrace();
    continue;
    }
    }

    }

    @OnError
    public void OnError(Session session, Throwable error){
    System.out.println("发生错误");
    error.printStackTrace();
    }

    public void sendMessage(String message) throws IOException{
    this.session.getBasicRemote().sendText(message);
    //this.session.getAsyncRemote().sendText(message);
    }

    public static synchronized int getOnlineCount() {
    return onlineCount;
    }

    public static synchronized void addOnlineCount() {
    WebsocketTest.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
    WebsocketTest.onlineCount--;
    }
    }

      3.服务端主动推送:SSE(Server Send Event)

        简介:

        SSE(Server-Sent Events,服务器发送事件)是围绕只读Comet 交互推出的API 或者模式。 

        SSE API允许网页获得来自服务器的更新(HTML5),用于创建到服务器的单向连接,服务器通过这个连接可以发送任意数量的数据。

        服务器响应的MIME类型必须是text/event-stream,而且是浏览器中的JavaScript API 能解析格式输出。

        SSE 支持短轮询、长轮询和HTTP 流,而且能在断开连接时自动确定何时重新连接。

        SSE是html5新标准,用来实现从服务端实时推送数据导浏览器端

        直接建立在当前http协议上,本质上是保持一个http长连接,轻量级协议

        适用于简单的服务器数据推送场景,使用服务器推送事件

        学习资料:https://www.w3school.com.cn/html5/html_5_serversentevents.asp

    前端代码

    客户端只需要直接使用**window.EventSource**对象,然后调用该对象的相应方法即可。   

     

    //判断是否支持SSE
    if('EventSource' in window){

    //初始化SSE
    var url="http:localhost:8080/test/push";
    var source=new EventSource(url);

    //开启时调用
    source.onopen=(event)=>{

    console.log("开启SSE");

    }

    //监听message事件
    source.onmessage=(event)=>{

    var data=event.data;

    $("body").append($("<p>").text(data));

    }

    //监听like事件
    source.addEventListener('like',function(event){

    var data=event.data;

    $("body").append($("<p>").text(data));
    },false);

    //发生异常时调用
    source.onerror=(event)=>{

    console.log(event);

    }

    服务端代码

    由于SSE是http请求,但是又限定是一个长连接,所以要设置MIME类型为text/event-stream。返回的为字符串。

    /**
    * SSE后台controller
    * @author like
    *
    */
    @Controller
    @RequestMapping(value="/test")
    public class TestSSEController {

    @ResponseBody
    @RequestMapping(value="/push",produces="text/event-stream;charset=UTF-8")
    public String push(HttpServletResponse res){

    res.setHeader("Access-Control-Allow-Origin","*");

    Date date=new Date();
    SimpleDateFormat sdf=new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
    String nowDate=sdf.format(date);

    return "data: 我是一个data 现在时间是"+nowDate+" event:like retry:5000 ";

    }
    }

    消息体格式

    服务器向浏览器发送的 SSE 数据,必须是 UTF-8 编码的文本;

    每一次发送的信息,由若干个message组成,每个message之间用 分隔。每个message内部由若干行组成;

    格式

    [field]:value
    

    其中field可以为四种

    1. data
    2. event
    3.  id
    4.  retry

    data代表数据,event代表事件名称,id代表id,retry代表多少时间轮训一次。


    所以我的服务端写的消息就可以翻译为:事件名称为**like**,数据为**我是一个data 现在时间是+当前时间**,每5秒轮训一次

    data: 我是一个data 现在时间是"+nowDate+" 
    event:like
     retry:5000
    
    

     

    SSE与WebSocket有相似功能,都是用来建立浏览器与服务器之间的通信渠道。两者的区别在于:

    • WebSocket是全双工通道,可以双向通信,功能更强;SSE是单向通道,只能服务器向浏览器端发送。
    • WebSocket是一个新的协议,需要服务器端支持;SSE则是部署在 HTTP协议之上的,现有的服务器软件都支持。
    • SSE是一个轻量级协议,相对简单;WebSocket是一种较重的协议,相对复杂。
    • SSE默认支持断线重连,WebSocket则需要额外部署。
    • SSE支持自定义发送的数据类型。
    • SSE不支持CORS 参数url就是服务器网址,必须与当前网页的网址在同一个网域(domain),而且协议和端口都必须相同。

       

  • 相关阅读:
    数据库事务的特性以及隔离级别
    非受检异常(运行时异常)和受检异常的区别等
    在测试crontab执行脚本的时候,修改了linux的系统时间,crontab不执行了。
    perl的foreach循环的坑
    javascript中快速求数组的全部元素的相加之和
    js 百度地图
    PHP 取前一天或后一天、一个月时间
    php截取字符串函数
    js jquery 基本元素操作
    PHP 替换标签和标签内的内容
  • 原文地址:https://www.cnblogs.com/fujingtao5470/p/11634835.html
Copyright © 2011-2022 走看看