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>