赞
踩
目录
主流的Web端即时通讯方案大致有4种:传统Ajax短轮询、Comet技术、WebSocket技术、SSE(Server-sent Events)。
Ajax短轮询 | Comet | WebSocket | SSE | |
---|---|---|---|---|
概念 | http端轮询是服务器收到请求不管是否有数据都直接响应 http 请求; 浏览器受到 http 响应隔一段时间在发送同样的http 请求查询是否有数据; | http 长轮询是服务器收到请求后如果有数据, 立刻响应请求; 如果没有数据就会 hold 一段时间,这段时间内如果有数据立刻响应请求; 如果时间到了还没有数据, 则响应 http 请求;浏览器受到 http 响应后立在发送一个同样http 请求查询是否有数据; | WebSocket的实现了一次连接,双方通信的功能。首先由客户端发出WebSocket请求,服务器端进行响应,实现类似TCP握手的动作。这个连接一旦建立起来,就保持在客户端和服务器之间,两者之间可以直接的进行数据的互相传送。 | 在 sse 的场景下,客户端发起请求,连接一直保持,服务端有数据就可以返回数据给客户端,这个返回可以是多次间隔的方式。sse 是单通道,只能服务端向客户端发消息 |
协议 | http | http | wbSocket | http |
短轮询 | 长轮询 |
使用接口模拟发送消息
- package com.asyf.demo.controller;
-
- import cn.hutool.core.date.DateUtil;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.ResponseBody;
- import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
-
- import java.io.IOException;
- import java.util.Date;
- import java.util.Map;
- import java.util.concurrent.ConcurrentHashMap;
-
-
- @Controller
- @RequestMapping(path = "sse")
- public class SSEController {
-
- @GetMapping(path = "")
- public String index() {
- //index.html在static/index.html目录
- return "index.html";
- }
-
- @RequestMapping(value = "test", method = RequestMethod.GET)
- public Object test() {
- return DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
- }
-
- private static Map<String, SseEmitter> sseCache = new ConcurrentHashMap<>();
-
- @GetMapping(path = "subscribe")
- public SseEmitter push(String id) throws IOException {
- System.out.println(id);
- // 超时时间设置为1小时
- SseEmitter sseEmitter = new SseEmitter(3600_000L);
- // 设置前端的重试时间为1s
- sseEmitter.send(SseEmitter.event().reconnectTime(1000).data("连接成功"));
- sseCache.put(id, sseEmitter);
- sseEmitter.onTimeout(() -> sseCache.remove(id));
- sseEmitter.onCompletion(() -> System.out.println("完成!!!"));
- return sseEmitter;
- }
-
- @GetMapping(path = "push")
- @ResponseBody
- public String push(String id, String content) throws IOException {
- SseEmitter sseEmitter = sseCache.get(id);
- if (sseEmitter != null) {
- sseEmitter.send(content);
- }
- return "push over";
- }
-
- @GetMapping(path = "close")
- @ResponseBody
- public String over(String id) throws IOException {
- SseEmitter sseEmitter = sseCache.get(id);
- if (sseEmitter != null) {
- sseEmitter.send("close");
- sseEmitter.send(SseEmitter.event().name("close").id(id).data(""));
- sseEmitter.complete();
- sseCache.remove(id);
- }
- return "close over";
- }
-
- }
目录是resourses/static/index.html
- <!doctype html>
- <html lang="en">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <title>SSE测试</title>
- </head>
- <body>
- <div>sse测试</div>
- <div id="result"></div>
- </body>
- </html>
- <script>
- function msg(msg) {
- console.log(msg)
- var div = document.createElement('div');
- div.innerHTML = msg;
- document.getElementById('result').appendChild(div);
- }
-
- //判断浏览器是否支持SSE
- if (!!window.EventSource) {
- var source = new EventSource('http://localhost:8080/sse/subscribe?id=ssetest');
-
- //响应消息-实现方式1
- // source.onmessage = function (event) {
- // text = document.getElementById('result').innerText;
- // text += '\n' + event.data;
- // document.getElementById('result').innerText = text;
- // };
-
- //响应消息-实现方式2
- source.addEventListener('message', function (e) {
- msg(e.data);
- }, false);
-
- //响应open事件
- source.addEventListener('open', function (e) {
- msg("连接打开.");
- }, false);
-
- // 响应close事件,主动关闭EventSource
- //后端关闭SSE会执行error事件,在error事件中关闭SSE不友好,后端在关闭SSE发送close
- // 事件以友好的关闭SSE
- source.addEventListener('close', function (e) {
- source.close();
- console.log(e);
- msg("数据接收完毕,关闭EventSource");
- }, false);
-
- //响应error事件
- source.addEventListener('error', function (e) {
- if (e.readyState == EventSource.CLOSED) {
- msg("连接关闭");
- } else {
- console.log(e);
- }
- }, false);
-
- } else {
- console.log("你的浏览器不支持SSE");
- msg("你的浏览器不支持SSE");
- }
-
- </script>
发送消息:http://localhost:8080/sse/push?id=ssetest&content=%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE
关闭连接:http://localhost:8080/sse/close?id=ssetest
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。