085_html5服务器发送事件

本文介绍了服务器发送事件(Server-Sent Event)技术,它允许网页从服务器自动获取更新,不再需要轮询。通过EventSource对象,浏览器可以监听来自服务器的事件流。示例代码展示了一个Servlet如何发送事件流,并在HTML页面上实时显示更新的商品数量。该技术在所有主流浏览器中得到支持,除了Internet Explorer。

1. html5服务器发送事件(server-sent event)允许网页获得来自服务器的更新。

2. Server-Sent事件 - 单向消息传递

2.1. Server-Sent事件指的是网页自动获取来自服务器的更新。

2.2. 以前也可能做到这一点, 前提是网页不得不询问是否有可用的更新。通过服务器发送事件, 更新能够自动到达。

3. 浏览器支持: 所有主流浏览器均支持服务器发送事件, 除了Internet Explorer。

4. 接收Server-Sent事件通知

4.1. EventSource 对象用于接收服务器发送事件通知:

var es = new EventSource("http://localhost:8080/EventSource/SAR2C.action");

es.onmessage = function(messageEvent) {
	document.getElementById("result").innerHTML += messageEvent.data + "<br />";
};

4.2. 创建一个新的EventSource对象, 然后规定发送更新的页面的URL(本例中是: "http://localhost:8080/EventSource/SAR2C.action"), 必须是全路径。

4.3. 每接收到一次更新, 就会发生onmessage事件。

4.4. 当onmessage事件发生时, 把已接收的数据推入id为"result"的元素中。

5. 检测Server-Sent事件支持

if(typeof(EventSource) !== "undefined") {

} else {

}

6. 服务器端代码实例

6.1. 为了让上面的例子可以运行, 您还需要能够发送数据更新的服务器(比如: Servlet、PHP和ASP)。

6.2. 新建一个名叫EventSource的动态Web工程

6.3. 编写ServerAutoRefresh2Client.java, 服务器端事件流的语法是非常简单的。把"Content-Type"报头设置为"text/event-stream"。现在, 您可以开始发送事件流了。

package com.lywgames.mysessionlistener;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServerAutoRefresh2Client extends HttpServlet {
	private static final long serialVersionUID = 1L;
	int id = 0;
	long startTime = 0;
	long endTime = 0;
	int goodsCount = 9999;
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String lastEventId = req.getHeader("Last-Event-ID");
		startTime = endTime;
		endTime = new Date().getTime();
		System.out.println("lastEventId = " + lastEventId + ", 2次请求时间间隔:" + (endTime - startTime));
		
		resp.setContentType("text/event-stream");

		OutputStream os = new BufferedOutputStream(resp.getOutputStream());
		// id,retry,data,之后必须使用两个\n\n(不然客户端取不到值)。
		// id最好放在最前面。req.getHeader("Last-Event-ID"); 在谷歌、safari浏览器有值, 火狐浏览器为null。
		os.write(("id:" + (++id) + "\n\n").getBytes());
		// 声明浏览器在连接断开之后进行再次连接之前的等待时间 10秒
		// 火狐浏览器默认5s请求一次, 谷歌浏览器默认3s请求一次, safari浏览器默认3s请求一次。
		os.write(("retry:" + (10 * 1000) + "\n\n").getBytes());
		os.write(("data:还有"+(goodsCount--)+"件商品。\n\n").getBytes());
    	os.flush();
    	os.close();
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req, resp);
	}
}

6.4. EventSource.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>获得服务器更新</title>
	</head>
	<body>
		商品数量:<div id="result"></div>
	
		<script>
			if(typeof(EventSource) !== "undefined") {
				// 必须是全路径
				var es = new EventSource("http://localhost:8080/EventSource/SAR2C.action");
				es.onopen = function(event) {
				
				}
				
				es.onmessage = function(messageEvent) {
					document.getElementById("result").innerHTML += messageEvent.data + "<br />";
				};
				
				es.onerror = function(event) {
				
				};
			} else {
				document.getElementById("result").innerHTML = "抱歉,您的浏览器不支持 server-sent 事件 ...";
			}
		</script>
	</body>
</html>

6.5. 运行项目

7. EventSource 对象

7.1. 在上面的例子中, 我们使用onmessage事件来获取消息。不过还可以使用其他事件:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值