使用htmlunit实现带有Ajax复杂页面的静态化技术

  1·最近项目要求要把网站的首页静态化,网站的首页是和多个jsp页面组成,整体显示的时候大概5000多行,比较困难的地方是很多地方由于做了jquery特效,所以当初直接使用$.ajax获取的数据,并直接生成的html.其中又包括了一些处理逻辑,如

if(0 == li.length){
				if(2==data.columncaption.length){//样式补位
					li = $('
  • '+data.columncaption+'
  • '); }else{ li = $('
  • '+data.columncaption+'
  • '); } $('#BookrackUL').append(li); var div=$('

    '+data_caption+'

    '); $('#BookrackDiv').append(div); j=1; }else{ if(0==j%5){//第一次创建一个div k=k+1; var div=$('

    '+data_caption+'

    '); $('#'+id+'fdiv').append(div); }else if(4==j%5){//样式调整 var pp=$('

    '+data_caption+'

    '); $('#'+id+'div'+k+'').append(pp); }else{//其他正常 var pp=$('

    '+data_caption+'

    '); $('#'+id+'div'+k+'').append(pp); } j=j+1; }

    原本是打算使用比较流行的freemaker来实现首页静态化,但以前没用过很难用freemaker标签实现这种效果.

      2·静态化还有一种思路就要采用HttpClient获取首页生成的html文件保存作为静态页,但是很不幸的,HttpClient无法执行js,所有使用ajax获取的数据都无法获取到,于是这种方式也行不通

      3·最后使用HtmlUnit.HtmlUnit的优势就是可以支持大部分js,对JQuery的支持也不错.大体思路就是先使用HtmlUnit获取执行完js的html,这个html生成的样式和html格式会出现一些问题.如果能满足需求则可以直接使用或者略加改动后使用.

    如果这个html不能满足需求,那么就把它当做为静态数据来使用.这个时候我们先需要一个html模板文件,这个模板文件要保证首页的主题框架,然后从html按照各个div将数据填充进去.下面贴一些实现代码.

    //创建一个可执行js,css,ajax的多功能WebClient
    				WebClient multiWebClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_8);
    				multiWebClient.setJavaScriptEnabled(true);//执行JavaScript
    				multiWebClient.setCssEnabled(true);//执行css
    				multiWebClient.setAjaxController(new NicelyResynchronizingAjaxController());//设置ajax代理
    				
    				//创建一个普通的WebClient
    				WebClient commmonWebClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_8);
    				commmonWebClient.setJavaScriptEnabled(false);
    				commmonWebClient.setCssEnabled(false);
    				
    				//用多功能Client获取动态页面的html并执行完js后的页面
    				URL dynamicUrl = new URL("http://localhost:30010/WebSite");
    				HtmlPage dynamicPage = (HtmlPage) multiWebClient.getPage(dynamicUrl);
    				
    				//根据项目需要,使用普通Client加载首页模板(避免执行模板里面的js,这些js都是真正要浏览器查看的时候才会执行)
    				URL constantUrl = new URL("http://localhost:30010/WebSite/wwwroot/indexTemple.html");
    				HtmlPage htmlpage = (HtmlPage) commmonWebClient.getPage(constantUrl);
    				HtmlElement body = htmlpage.getBody(); 
    				
    				/**
    				 * 未详细测试的结论:getElementById一个元素只能取一次,取了之后再取就是空元素,其子也无法用getElementById取到
    				 * 开始处理header
    				 */
    				appendChildren(body.getElementById("_static_nav"), dynamicPage.getElementById("_static_nav"));
    				
    				//开始处理_static_leftbox
    				//处理图片滚动KSS_content
    				appendChildren(body.getElementById("KinSlideshow"), dynamicPage.getElementById("KSS_content"));
    				//处理最新电子书
    				appendChildren(body.getElementById("e_bookDiv"), dynamicPage.getElementById("e_bookDiv"));
    				
    				//取出content
    				HtmlElement content = body.getElementById("content");
    				
    				//开始处理_static_rightbox
    				content.appendChild(dynamicPage.getElementById("_static_rightbox"));
    				//添加div换行
    				DomElement clearDiv = htmlpage.createElement("div");
    				clearDiv.setAttribute("class", "clear");
    				//一个DomElement貌似只能使用一次
    				content.appendChild(clearDiv.cloneNode(true));
    				
    				//开始处理_static_bookshow
    				content.appendChild(dynamicPage.getElementById("_static_bookshow"));
    				content.appendChild(clearDiv.cloneNode(true));
    				
    				//开始处理_static_assistBox,secrecyRelevancediv,_static_optionBox
    				content.appendChild(dynamicPage.getElementById("_static_assistBox"));
    				content.appendChild(dynamicPage.getElementById("secrecyRelevancediv"));
    				content.appendChild(dynamicPage.getElementById("_static_optionBox"));
    				content.appendChild(clearDiv.cloneNode(true));
    				
    				//开始处理_static_bookShowA
    				content.appendChild(dynamicPage.getElementById("_static_bookShowA"));
    				content.appendChild(clearDiv.cloneNode(true));
    				//开始处理_static_serve
    				content.appendChild(dynamicPage.getElementById("_static_serve"));
    				
    				//开始处理footer
    				body.appendChild(clearDiv.cloneNode(true));
    				body.appendChild(dynamicPage.getElementById("_static_footer"));
    				
    				
    				//处理错误
    				String finalHtml =htmlpage.asXml().replace("", ""); 
    				finalHtml = finalHtml.replaceAll("", "");
    				finalHtml = finalHtml.replaceAll("", "");
    				finalHtml = finalHtml.replaceAll("", "");
    				finalHtml = finalHtml.replaceAll("scrollable_2", "scrollable");
    				stringToFile(finalHtml,"E:\\WayOfGlory\\WebSite\\WebContent\\wwwroot\\indexHome.html");

       上面一段代码虽然不长,但实际上是个非常漫长的处理过程,从静态数据html中获取到的

    经常会无法直接使用,这时就需要不断的和浏览器(比如chrome)生成的真正静态页进行比对.虽然过程很漫长,但总比无法实现要强.

       下面贴上刚刚使用了的两个小方法.

        	public DomElement appendChildren(DomElement target,DomElement source){
        		
    			Iterator it = source.getChildElements().iterator();
    			while(it.hasNext()){
    				DomElement ele = (DomElement) it.next();
    				target.appendChild(ele);
    			}
        		return target;
        	}
        	
        	
    
        	public void stringToFile(String content,String path){
        		try {
    				FileWriterWithEncoding fileWriter = new FileWriterWithEncoding(path,"utf-8");
    				fileWriter.write(content);
    				fileWriter.flush();
    				fileWriter.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
        	}

       这种实现是自己瞎研究的,如果有哪位大虾有更好的方法,欢迎指点.

    你可能感兴趣的:(mvc)