本页目录
- SSE介绍
- SSE的数据格式
- SpringBoot接入SSE
- 前端代码
- 后端代码
- 测试
SSE介绍
SSE则是部署在 HTTP协议之上的,现有的服务器软件都支持此协议。
SSE是一个轻量级协议,相对简单;WebSocket是一种较重的协议,相对复杂。但SSE只支持单向交互(服务器给客户发送),Websocket支持双向交互。
SSE默认支持断线重连,WebSocket则需要额外部署。
数据格式方面, SSE 使用的是 UTF8 编码的文本格式。
SSE的HTTP response 里header Content-Type 的值是 text/event-stream。不可变!
SSE的数据格式
每个SSE的消息响应分为4个元素:
- retry:重试时间,单位毫秒,只能为数字(SSE请求失败,就会发送新的请求)
- id:消息ID(自定义)
- event:时间类型(自定义)
- data:消息的内容(自定义)
下图是4个消息,注意,多个消息之间中间会有个空行(nn)。单个消息之间元素间隔是换行n
代码语言:javascript复制retry: 5000
id: 1cd7bb64-4341-4f5d-a690-4298b8a8ae20
event: eventType
data: Sun Nov 20 18:23:11 CST 2022
retry: 5000
id: 2f57295d-3eaa-4e5c-a787-55fff58d9b05
event: eventType
data: Sun Nov 20 18:23:12 CST 2022
retry: 5000
id: 6a9618de-99e7-4c03-91f8-dcdd7601a8d0
event: eventType
data: Sun Nov 20 18:23:13 CST 2022
retry: 5000
id: c5fdcc90-b1f7-4058-9a3a-d63881ffea8b
event: eventType
data: Sun Nov 20 18:23:14 CST 2022
SpringBoot接入SSE
不依赖于任何Jar包,本质只是一个Http协议,然后指定ContentType,然后返回相应的格式!
前端代码
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SSE链接测试</title>
</head>
<body>
消息类型是message消息:
<div id="ssediv">默认消息</div>
<br>
消息类型是diyEventType消息:
<div id="diyssediv">DIY SSE消息</div>
</body>
<script>
var sse = new EventSource("http://localhost:8081/sse");
/**
* 默认是没有指定eventTtpe的消息,但eventType就为message。
* 等价于addEventListener("message" ...
*/
sse.onmessage = function (ev) {
console.error("这里只能处理eventType为message的消息")
var elementById = document.getElementById("ssediv");
elementById.innerHTML = ev.data;
}
/**
* 添加指定类型消息处理,eventType是后台自定义的
*/
sse.addEventListener("diyEventType",event => {
console.error("自定义事件" event.data)
var elementById2 = document.getElementById("diyssediv");
elementById2.innerHTML = event.data;
})
/**
* SSE连接异常
*/
sse.onerror = function (){
alert("服务器已停止!")
}
/**
* SSE连接成功
*/
sse.onopen = function (){
alert("服务器已连接!")
}
// 不要忘记关闭断开连接哦
// sse.close()
</script>
</html>
后端代码
代码语言:javascript复制@Controller
public class SSE {
@GetMapping(value = "/sse")
@ResponseBody
public String getMessage(HttpServletResponse response) {
// System.out.println("请求进入了");
response.setContentType("text/event-stream"); // 指定ContentType,不可变
response.setCharacterEncoding("utf-8"); // 指定响应字符集,是否可变,没测试,但建议指定utf-8
while (true) {
String s = "";
s = "retry: 5000n"; // 客户端没有获取到数据,就不断发送新的请求(间隔5秒),直到有数据。
s = "id: " UUID.randomUUID() "n"; // 这里指定消息ID
s = "event: eventTypen"; // 这里定义事件类型,自定义!
s = "data: " new Date() "nn"; // 这里设置返回的数据
try {
PrintWriter pw = response.getWriter();
Thread.sleep(1000L);
pw.write(s);
pw.flush();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
测试
注意避免跨域,浏览器URL用localhost,前端SSE的URl不能是127.0.0.1。
如果Jmeter直接打到请求上,200个连接,直接导致任何请求无法进行。停止Jmeter后,依旧无法进行请求。lsof -i:服务端口,都是closed也无法
特殊说明: 以上文章,均是我实际操作,写出来的笔记资料,不会盗用别人文章!烦请各位,请勿直接盗用!转载记得标注来源!