消息推送现在基本上是web应用的标配,在做一个社交类网站时,本人一开始由于对这方面的技术不够熟练,想采用最新的websocket技术,却一直失败,最终采用了最传统的轮询方式,十分浪费资源。今天看了spring boot 实战这本书,里面介绍了一种我之前从未了解过的技术——服务器推送事件(Server-sent Events),简称SSE,它可以很方便地实现服务器向客户端的单向消息推送,看起来相当简单,遂动手尝试了一下,用起来果然十分方便,因此在此作个笔记,以便日后使用。
在这我就不对这项技术的内部实现进行深入探讨了,只谈谈它如何应用。博主在这里使用的是java语言,其他语言也类似:
首先创建一个java web项目,新建一个简单的首页,代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>测试页面</title>
<style>
</style>
</head>
<body class="bgBody">
<div id="msgFromPush"></div>
<script src="<%=request.getContextPath()%>/resources/js/jquery-1.11.3.min.js"></script>
<script type="text/javascript">
//jsp页面js脚本
var source = new EventSource('push');//发送消息
s = '';
source.addEventListener('message', function(e) {
s += e.data + "<br/>";
$("#msgFromPush").html(s);
},false);//添加客户端的监听
source.addEventListener('open', function(e) {
console.log("连接打开");
}, false);
source.addEventListener('error',function(e){
if(e.currentTarget.readyState==EventSource.CLOSED){
console.log("连接关闭");
}else{
console.log(e.currentTarget.readyState);
}
});
</script>
</body>
</html>
其中最核心的就是EventSource()对象了,对象里的参数就是服务器推送的请求路径了,要注意的是,EventSource目前并不为IE所支持,请在谷歌或火狐等浏览器下尝试。
eventSource最核心的函数有以下几个:
我们可以像实例代码一样通过注册监听器实现推送接送功能,也可以使用以下这种形式:source.onXXXX=function(e){...}实现。接下来看服务器端的代码:
* 实现服务器推送
* @param response
* @return
*/
@RequestMapping(value="push",produces="text/event-stream")
@ResponseBody
public String push(HttpServletResponse response){
Random random=new Random();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "data:Testing 1,2,3"+random.nextInt()+"\n\n";
}
服务器端无需要使用第三方jar包,只要修改一下响应头信息就可以实现推送功能了。要注意的是,推送的数据格式是有规定的, 都是如下格式:
field: value\n
field可以取四个值:“data”, “event”, “id”, or “retry”,也就是说有四类头信息。每次HTTP通信可以包含这四类头信息中的一类或多类。\n代表换行符。
以冒号开头的行,表示注释。通常,服务器每隔一段时间就会向浏览器发送一个注释,保持连接不中断。
数据内容用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
大家千万要记得结尾要两个换行符,否则前端是无法正确处理数据的,博主可是被这个坑了好久。