java实现bigpipe(上)

   之前一个同学问我搞过bigpipe没有,当时也不知道这个是什么东东,网上找了一些资料之后自己实现了一个。

  bigpipe的大体思路是分解网页成叫做Pagelets的小块,然后通过Web服务器和浏览器建立管道并管理他们在不同阶段的运行。
    具体的概念和优缺点就不在这里复制粘贴了,网上一大把,有兴趣的可以在: http://www.searchtb.com/2011/04/an-introduction-to-bigpipe.html 看一看

  bigpipe的页面结构很简单,它分成主页面和子页面(pagelet)2个部分。
服务器向浏览器发送响应时候,先把主页面的内容flush出来。然后服务器开启数个线程对各个子页面进行处理,完成之后一个一个flush到主页面的底部。



  先看一下主页面代码例子:

<body>
<div id="p1"></div>
<div id="p2"></div>
<div id="p3"></div>
sdfsfasfdafsdf
</body>


  例子很简单,p1、p2、p3就是用来定义3个pagelet的位置的。当子页面被flush到页面尾部后,通过一个json字符串定义子页面的内容、样式、和javascript代码。

  json格式如下:

{
pid:string,  //pid定义了这个pagelet需要放置的页面位置,对应主页面的p1、p2、p3
css:string,  //定义该pagelet需要用到的css文件
js:Array,    //定义pagelet用到的数个js文件
html:string  //pagelet的html内容
}  
  
 根据这个json的格式后台给页面输出的内容大概是这样样子的:

<script>bigpipe.create({"css":"/bigpipe/css/page2.css","html":"\r\n\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n2:null <br>\r\n\r\n","js":["/bigpipe/js/page2.js"],"path":"/pagelet2.jsp","pid":"p2"});</script>

每一个pagelet被flush之后会立即调用bigpipe.create:

var bigpipe = (function () {
	
	var headObj = document.getElementsByTagName("head")[0];
	var bodyObj = document.getElementsByTagName("body")[0];

 
	function loadCss(obj,fn) {	
		var link = document.createElement("link");
		link.rel = "stylesheet";
		link.type = "text/css";
		link.href = obj.css;
		headObj.appendChild(link);	
		Event.bind(link,"load",function(){
			fn(obj);
		});
	}
	function loadJs(jsSrc) {
		var script = document.createElement("script");
		script.type = "text/javascript";
		script.src = jsSrc;
		bodyObj.appendChild(script);
	}
	
	return {
		create:function (obj) { 
			if (!obj.pid) {
				return;
			}
			var fn=function(obj){    //注意一下这里,html和js不是立即写入页面中,而是作为回调函数等css加载完毕后再写入。
				Log.d(obj);
				document.getElementById(obj.pid).innerHTML=obj.html; //指定位置填写html代码
				for(var i=0,len=obj.js.length;i<len;i++){  
					loadJs(obj.js[i]); //加载js文件
				}
			}
			loadCss(obj,fn);		//加载css
		}
	};
})();

  pagelet组件加载的顺序是:css-->html-->js。由于css是异步加载的,如果先写入html再加载css可能会影响用户体现,为了保证让css加载完毕后才显示网页内容,注意一下loadcss方法,这里是等到css加载完毕后才写入html和加载js。



    代码如附件(注:这里用到了公司的一个写日志的jar包,压缩包里是没有的,如果想编译通过把openEAP的依赖去掉然后把所有写日志的部分注释掉就行)

你可能感兴趣的:(java,Web)