SSE实现后端向前页面推送实时数据,是长链接不是连接一次就断开

新接触sse,从网上找了好多资料都是在后端retuen数据给页面,这样导致了页面的长链接就断开了,然后我就改了下它,如果有其他更简便的方式,请大佬们告诉我
直接上代码

后端接口:

后端我是集成了swagger页面,然后通过swagger调用接口给statusMap中更改用户Id的状态,前端页面就能实时显示了

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Administrator
 * @Title: SSEController
 * @ProjectName project_back
 * @Description: TODO
 * @date 2019/10/249:38
 */
@RestController
@RequestMapping("/SSEController")
@Api(tags = "sse服务")
public class SSEController {
    //produces = "text/event-stream;charset=UTF-8"一定要带上
    static Map<String,HttpServletResponse> responseMap = new HashMap<>();
    static Map<String,String> statusMap = new HashMap<>();
    @ApiOperation("开启sse服务")
    @GetMapping(value = "/get_data", produces = "text/event-stream;charset=UTF-8")
    public void push(@RequestParam(name = "userId")String userId,HttpServletResponse response){
        System.out.println("调用开启连接的接口!====");
        responseMap.put(userId,response);
        try {
            while (true){
                Thread.sleep(100);
                //数据格式必须为下面这种格式,"data:"+你的数据+"\n\n";  "data"还有其他的格式, “data”, “event”, “id”,“retry”,
                String data = "data:" + userId + "的状态为:"+ getStatus(userId) + "\n\n";
                if (null != responseMap.get(userId)){
                    response.setHeader("Content-Type", "text/event-stream;charset=UTF-8");
                    PrintWriter writer = response.getWriter();
                    writer.print(data);
                    writer.flush();
                }else {
                    break;
                }
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("sse连接已断开");
    }
    @ApiOperation("发送数据")
    @PostMapping("/send")
    public void send(@RequestParam(name = "userId")String userId,@RequestParam(name = "status")String status) {
        statusMap.put(userId,status);
    }
    @ApiOperation("关闭连接")
    @GetMapping("/close")
    public void close(@RequestParam(name = "userId")String userId) {
        System.out.println("调用连接关闭接口!!!==============");
        responseMap.remove(userId);
    }

    public String getStatus(String userId){
        String status = statusMap.get(userId);
        if (null == status){
            status = "空";
        }
        return status;
    }
}

前端页面使用的html:

运行的时候使用nginx代理的页面

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>

    <script type="text/javascript">
        //需要判断浏览器支不支持,可以去w3c进行查看
        //关闭页面时触发的方法,关闭长链接
        window.onbeforeunload = function(){
            closeo();
        };
        var source = new EventSource('http://localhost:8080/SSEController/get_data?userId=1111111111');
        source.readyState;
        // EventSource.CLOSED
        source.onmessage = function (event) {
            console.info(event.data);
            document.getElementById('result').innerText = event.data
        };
        source.onopen = function () {
            console.info("链接已经打开");
        };
        source.onerror = function () {
            console.info("连接出错");
        };
        function openo(){
            console.info("正在打开连接")
            source = new EventSource('http://localhost:8080/SSEController/get_data?userId=1111111111');
        };
        function closeo(){
            console.info("断开链接");
            source.close();
            $.ajax({
                type: "GET",
                url: "http://localhost:8080/SSEController/close?userId=1111111111",
                data: '',
                dataType: "JSON",
                success: function(ret) {
                }
            });
        };
    </script>
</head>
<body>
<div id="result">
</div>
<div>
    <button onclick="closeo()">断开</button>
    <button onclick="openo()">重新连接</button>
</div>
</body>
</html>

页面效果:

SSE实现后端向前页面推送实时数据,是长链接不是连接一次就断开_第1张图片
我这种方式是根据前端调用接口来控制长链接的连接和断开,现在就是有个问题,我接口使用的HttpServletResponse给页面返回数据,但是我想写成异步的方式时HttpServletResponse就报空指针,大佬们有没有新的方式,我觉得这种方式比较low…

你可能感兴趣的:(笔记,SSE,长链接,http流,后端向前端实时推送)