springboot服务端消息推送(SSE技术)
SSE技术是基于单工通信模式,只是单纯的客户端向服务端发送请求,服务端不会主动发送给客户端。服务端采取的策略是抓住这个请求不放,等数据更新的时候才返回给客户端,当客户端接收到消息后,再向服务端发送请求,周而复始。
注意:因为EventSource对象是SSE的客户端,可能会有浏览器对其不支持,但谷歌、火狐、360是可以的,IE不可以。
另外WebSocket技术是双工模式。
data:数据栏
数据内容用data表示,可以占用一行或多行。每行以data:开始,如果数据只有一行,则像下面这样,以“\n\n”结尾。
data:message\n\n
如果数据有多行,则最后一行用“\n\n”结尾,前面行都用“\n”结尾。
data:begin message\n
data:continue message\n\n
总之,最后一行的data,结尾要用两个换行符号,表示数据结束。
以发送JSON格式的数据为例。
data:{\n
data:"foo": "bar",\n
data:"baz", 555\n
data:}\n\n
id:数据标识符
数据标识符用id表示,相当于每一条数据的编号。
id:msg1\n
data:message\n\n
浏览器用lastEventId属性读取这个值。一旦连接断线,浏览器会发送一个HTTP头,里面包含一个特殊的“Last-Event-ID”头信息,将这个值发送回来,用来帮助服务器端重建连接。因此,这个头信息可以被视为一种同步机制。
@Controller
public class MainController {
@GetMapping("/")
public String sse() {
return "sse";
}
@GetMapping(value="push",produces="text/event-stream")
@ResponseBody
public String push(){
System.out.println("push msg..");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//注意:返回数据的格式要严格按照这样写,data:开始 ‘\n\n’结束
return "data:current time: "+new SimpleDateFormat("YYYY-MM-dd hh:mm:ss").format(new Date())+"\n\n";
}
}
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>SSE方式消息推送</title>
</head>
<body>
<div id="msgFromPush"></div>
<script src="http://apps.bdimg.com/libs/jquery/1.11.3/jquery.min.js"></script>
<script type="text/javascript">
if(!!window.EventSource){
var source = new EventSource('push');
s = '';
source.addEventListener('message',function(e){
console.log("get message"+e.data);
s+=e.data+"<br/>";
$("#msgFromPush").html(s);
});
source.addEventListener('open',function(e){
console.log("connect is open");
},false);
source.addEventListener('error',function(e){
if(e.readyState == EventSource.CLOSE){
console.log("connect is close");
}else{
console.log(e.readyState);
}
},false);
}else{
console.log("web is not support");
}
</script>
</body>
</html>