Spring MVC SSE-服务端推送技术

  Web 项目中,浏览器与服务器是通过请求响应来实现功能功能交互的,当服务端出现新的信息需要让前端知道时,就需要用到服务器推送技术。

  服务端推送技术有基于SSE(Server Send Event 服务端发送事件)的服务器端推送,该方式需要浏览器支持,而目前主流浏览器最近版本基本都支持;基于Servlet 3.0+的异步方法特性;WebSocket双向通信技术。

SSE

  SSE(Server Send Event) 是 HTML 5 规范中的一部分。
  该技术主要由两个部分组成:第一个部分是服务器端与浏览器端之间的通讯协议,第二部分则是在浏览器端可供 JavaScript 使用的 EventSource 对象。通讯协议是基于纯文本的简单协议。服务器端的响应的内容类型是“text/event-stream”。
  响应文本的内容可以看成是一个事件流,由不同的事件所组成。每个事件由类型和数据两部分组成,同时每个事件可以有一个可选的标识符。不同事件的内容之间通过仅包含回车符和换行符的空行(\r\n)来分隔。

示例代码

  1. Controller
    服务端SSE支持的输出媒体类型为text/event-stream
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    package com.controller;

    import java.io.UnsupportedEncodingException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Random;

    import javax.servlet.http.HttpServletResponse;

    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;

    /**
    * 服务器端推送技术SSE(Server Send Event)
    * 输出的媒体类型:produces = "text/event-stream;charset=UTF-8"
    * 注意要添加返回消息的编码:charset=UTF-8
    * @author Rocky
    *
    */

    @Controller
    public class SseController {

    @RequestMapping("/sse")
    public String sseV() {
    return "sse";
    }

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

    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
    Random random = new Random();
    try {
    //每间隔5秒执行一次,奇怪的是目前测的是会延次3秒,即设的是5秒,但间隔的是8秒
    Thread.sleep(5000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    return "data:当前时间: " + sdf.format(new Date()) + "\n\n";
    }
    }

  2. sse.jsp
    EventSource 对象只有新式的浏览器才支持, 是 SSE的客户端。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    <%@ page language="java" contentType="text/html; charset=UTF-8"	pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

    <script type="text/javascript" src="${pageContext.request.contextPath}/static/js/jquery-1.11.0.js"></script>
    <!-- <script type="text/javascript" src="/static/js/jquery-1.11.0.js"></script> -->

    <script type="text/javascript">
    //EventSource对象需要浏览器支持
    if(!!window.EventSource){
    var source = new EventSource('push');
    s = '';
    //事件监听器,获取服务器推送的消息
    source.addEventListener('message',function(e){
    s+=e.data + "<br/>";
    $("#msgFromPush").html(s);
    });

    source.addEventListener('open',function(e){
    console.log("连接打开.");
    }, false);

    source.addEventListener('error',function(e){
    if(e.readyState == EventSource.CLOSED){
    console.log("连接关闭");
    }else{
    console.log(e.readyState);
    }
    }, false);

    }else{
    console.log("你的浏览器不支持SSE");
    }

    </script>

    <title>SSE Demo</title>
    </head>
    <body>
    <div id="msgFromPush"></div>
    </body>
    </html>

参考
SSE技术详解:一种全新的HTML5服务器推送事件技术
Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE

作者

光星

发布于

2018-04-01

更新于

2022-06-17

许可协议

评论