服务器实时通知客户端方案,服务器发送/推送事件方案(2)server event,典型例子,可以用作股票、新闻信息推送

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kkgbn/article/details/53159791

server event是html5规范的一部分,它相比websocket使用起来更简单,对服务器的改动也最小


前端html部分

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="result"></div>
<script>
	if(typeof(EventSource)!=="undefined")
	{
		var source=new EventSource("doevent");
		//打开连接
  		source.onopen=function(event)
    	{
  			console.log("onopen",event);
    	};
    	//错误信息
  		source.onerror=function(e)
    	{
  			console.log("err",e);
    	};
    	//处理接受到的消息
  		source.onmessage=function(event)
    	{
  			console.log("onmessage",event);
   	 		document.getElementById("result").innerHTML+=event.data + "<br />";
    	};
	}
	else
  	{
  		document.getElementById("result").innerHTML="Sorry, your browser does not support server-sent events...";
	}
</script>
</body>
</html>

服务器部分,其中最主要的是

①将返回的消息头的content_type设置为text/event-stream;

②返回的格式要以“data:”开头,前端收到后也是取event.data来得到信息;

③再就是返回需要加上两个换行。否则收不到MessageEvent的返回。




	@RequestMapping("/doEvent")
	void doEvent(HttpServletRequest req, HttpServletResponse resp)  throws ServletException, IOException
	{
		resp.setContentType("text/event-stream");
		resp.setHeader("expires", "-1");
		resp.setHeader("cache-control", "no-cache");
		String s = "data:"+new Date().toString()+"\n\n";
		resp.getOutputStream().write(s.getBytes());
	}



如果直接用spring 的controller返回值的的情况,会产生直接访问content_type消息头依然为text/html的情况,但是前端如果是使用的server event请求依然会得到text/stream的返回,因而不影响使用

	@RequestMapping("/doevent")
	@ResponseBody
	String doEvent(HttpServletRequest req, HttpServletResponse rsp){
		rsp.setContentType("text/event-stream");
		return "data:"+new Date().toString()+"\n\n";
	}



以上的介绍,大家对server event已经基本了解,并可以测试例子,的确实现了服务器往客户端推送不断消息。但其实这个经常被引用的例子在不断的建立和断开链接,成了类似前端轮询那样的机制,容易误导大家。

下面的例子是一直在连接的情况下不断的推送要描绘的位置信息,更典型也更易于理解server event的设计意图

	@RequestMapping("/doevent")
	void doEvent(HttpServletRequest req, HttpServletResponse resp)
	{
		HttpHeadTool.allowAccess(resp);
		LogCore.BASE.info("{} doevent", req.getSession().getId());
		resp.setContentType("text/event-stream");
		resp.setHeader("expires", "-1");
		resp.setHeader("cache-control", "no-cache");
		
		int i = 0;
		int r = 100; //半径
		int v = 50;  //走一圈的步数
	
		while(true){
			i = (i+1)%(v*2);
			if(i==0){
				r += 20;
			}
	                double angel = i*Math.PI/v;	//i 从   0到2π
			int x = (int)Math.round( r* Math.cos(angel) );
			int y = (int)Math.round( r* Math.sin(angel) );
			String s = "data:"+x+","+y+"\n\n";
			
			try {
				resp.getOutputStream().write(s.getBytes());
			} catch (Exception e) {
				LogCore.BASE.error(e.getMessage());
				return;
			}
			try {
				resp.flushBuffer();//前端页面关闭或刷新
			} catch (IOException e) {
				LogCore.BASE.error(e.getMessage());
				return;
			}
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				LogCore.BASE.error(e.getMessage());
				return;
			}
		}
	}

前端页面

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<div id="result"></div>
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
<style type="text/css">
    #box-container {
        position: relative;
        width : 800px;
        height : 600px;
    }
    #box {
        width : 40px;
        height : 40px;
        background-color : #f00;
        position : absolute;
    }
    #_lable {
        width : 20px;
        height : 20px;
        background-color : #00f;
        position : absolute;
    }
    #_origin {
        width : 5px;
        height : 5px;
        background-color : #00f;
        position : absolute;
    }
</style>
</head>
<body>
<div class="row-fluid">
    <div class="row10 offset2">
        <div class="page-header">
            <h1>Random Movement<small> HTML 5 server sent events sample</small></h1>
        </div>
    </div>
    <div id="box-container" class="row10 offset2">
        <div id="box"></div>
        <div id="_lable"></div>
        <div id="_origin"></div>
    </div>
</div>
<script>
	if(typeof(EventSource)!=="undefined")
	{
		var source=new EventSource("http://localhost:8084/doevent");
		//打开连接
  		source.onopen=function(event)
    	{
  			console.log("onopen",event);
    	};
    	//错误信息
  		source.onerror=function(e)
    	{
  			console.log("err",e);
    	};
    	//处理接受到的消息
  	source.onmessage=function(event)
    	{
  			console.log("onmessage",event);
   	 		document.getElementById("result").innerHTML=event.data + "<br />";
   	 		document.getElementById("_lable").innerHTML=event.data + "<br />";
   	 		var pos = event.data.split(',');
   	 		x = pos[0];
   	 		y = pos[1];
   	 		o_x = Number(document.body.clientWidth)/2;
   	 		o_y = Number(document.body.clientHeight)/2;
   	 		x = Number(x) + Number(o_x);
   	 		y = Number(y) + Number(o_y);
   	 		$('#box').css({
   				left :  x + 'px',
   				top : y + 'px'
   			});
   	 		$('#_lable').css({
				left : x + 'px',
				top : y + 'px'
			});
   	 		$('#_origin').css({
				left : o_x + 'px',
				top : o_y + 'px'
			});
    	};
	}
	else
  	{
  		document.getElementById("result").innerHTML="Sorry, your browser does not support server-sent events...";
	}
</script>
</body>
</html>


或者用canvas绘制

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<div id="result"></div>
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
<body>
	<canvas class="canvas" id ="canvas" style="background-color: red">
	</canvas>
<script>
	var canvas = document.getElementById("canvas");
	canvas.width = document.body.scrollWidth;
	canvas.height = document.body.scrollHeight;
	if(typeof(EventSource)!=="undefined")
	{
		var source=new EventSource("http://localhost:8084/doevent");
		//打开连接
  		source.onopen=function(event)
    	{
  			console.log("onopen",event);
    	};
    	//错误信息
  		source.onerror=function(e)
    	{
  			console.log("err",e);
    	};
    	//处理接受到的消息
  		source.onmessage=function(event)
    	{
  			console.log("onmessage",event);
   	 		document.getElementById("result").innerHTML=event.data + "<br />";
   	 		var pos = event.data.split(',');
   	 		x = pos[0];
   	 		y = pos[1];
   	 		o_x = Number(document.getElementById("canvas").clientWidth)/2;
   	 		o_y = Number(document.getElementById("canvas").clientHeight)/2;
   	 		x = Number(x) + Number(o_x);
   	 		y = Number(y) + Number(o_y);
   			var ctx = canvas.getContext("2d");

			ctx.beginPath();
			ctx.arc(x, y, 5, 0, 2 * Math.PI, false);
			ctx.stroke();
    	};
	}
	else
  	{
  		document.getElementById("result").innerHTML="Sorry, your browser does not support server-sent events...";
	}
</script>
</body>
</html>



bingo

猜你喜欢

转载自blog.csdn.net/kkgbn/article/details/53159791