最近项目中页面需要对大数量进行计数显示,sql执行过程就很慢,界面用户体验不好,所以采用了Ajax反转技术来实现后台动态推送.这样就可以将要显示的信息分批进行显示,一部分一部分往界面传送.让界面在短时间内有东西可以显示给用户,不至于让用户面对大白板.
反转AJAX:服务流应用到AJAX,就是所谓的反转AJAX 或者COMET 。它使得服务器在某事件发生时可以发送消息给客户端,而不需要客户端显式的请求。目标在于达到状态变化的实时更新。COMET使用了HTTP/1.1中的持续连接的特性。通过HTTP/1.1,除非另作说明,服务器和浏览器之间的TCP连接会一直保持连接状态,直到其中一方发送了一条明显的“关闭连接”的消息,或者有超时以及网络错误发生。
看具体使用方法.
首先需要配置web.xml,让服务器知道Ajax反转的存在
<!-- 1、piggyback方式
这是默认的方式。
如果后台有什么内容需要推送到前台,是要等到那个页面进行下一次ajax请求的时候,将需要推送的内容附加在该次请求之后,传回到页面。
只有等到下次请求页面主动发起了,中间的变化内容才传递回页面。
2、comet方式
当服务端建立和浏览器的连接,将页面内容发送到浏览器之后,对应的连接并不关闭,只是暂时挂起。如果后面有什么新的内容需要推送到客户端的时候直接通过前面挂起的连接再次传送数据。
服务器所能提供的连接数目是一定的,在大量的挂起的连接没有关闭的情况下,可能造成新的连接请求不能接入,从而影响到服务质量。
3、polling方式
由浏览器定时向服务端发送ajax请求,询问后台是否有什么内容需要推送,有的话就会由服务端返回推送内容。这种方式和我们直接在页面通过定时器发送ajax请求,然后查询后台是否有变化内容的实现是类似的。只不过用了dwr之后这部分工作由框架帮我们完成了。
-->
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>
org.directwebremoting.servlet.DwrServlet
</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
<!-- DWR默认采用piggyback方式 -->
<!-- 使用polling和comet的方式 -->
<init-param>
<param-name>pollAndCometEnabled</param-name>
<param-value>true</param-value>
</init-param>
<!-- comet方式 -->
<!--
<init-param>
<param-name>activeReverseAjaxEnabled</param-name>
<param-value>true</param-value>
</init-param>
-->
<!-- polling方式:在comet方式的基础之上,再配置以下参数 -->
<!--
<init-param>
<param-name>org.directwebremoting.extend.ServerLoadMonitor</param-name>
<param-value>org.directwebremoting.impl.PollingServerLoadMonitor</param-value>
</init-param>
-->
<init-param>
<param-name>crossDomainSessionSecurity</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
然后dwr.xml中的配置:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" " http://www.getahead.ltd.uk/dwr/dwr10.dtd ">
<dwr>
<allow>
<convert match="java.lang.Exception" converter="exception">
<param name='include' value='message'/>
</convert>
<convert match="java.lang.StackTraceElement" converter="bean"/>
<create creator="new" javascript="dwrPush" >
<param name="class" value="com.adtech.dwr.DwrPush" />
<include method="sendMessage"/>
</create>
<convert match="com.adtech.domain.Monitor" converter="bean" />
</allow>
</dwr>
后台Java代码:
public void myTest() throws Exception {
String strResult="";
for (int i = 1; i <= 5; i++) {
strResult="这是第"+i+"句话";
// 一个循环处理完后推送回界面
ScriptBuffer scriptBuffer = new ScriptBuffer();
// 推送回界面,调用客户端javascript function
scriptBuffer.appendScript("clientFun(").appendData(strResult).appendScript(");");
ServerContext sctx = ServerContextFactory.get(wctx .getServletContext());
Collection<ScriptSession> scriptSessions = sctx.getScriptSessionsByPage(wctx.getCurrentPage());
for (ScriptSession session : scriptSessions) {
session.addScript(scriptBuffer);
}
}
}
js界面部分代码:
//在js里需要有个初始方法,来调用Java里的方法
init : function(){
DWREngine.setAsync(true);
//调用action里方法,完成动态推送
Test.myTest(function(_data) {
});
DWREngine.setAsync(false);
}
//调用了Java方法后,Java方法在执行代码过程中会回调到js里的clientFun方法.
//推送回调的方法
clientFun = function (_data){
//在这个方法里js界面可以根据需求来完成想做的事,将返回的部分显示先展示出来
loadData(_data);
};
Ajax反转,所谓反转还是跟回调同样的思想,前台方法的调用是由服务器发起的,不需要客户端进行调用.使用Ajax异步操作.后台推送从字面上就能看出来这件事的进行是被动的,服务器是将数据推给客户端,客户端接收并处理.本次项目经过后台推送,速度快了很多,界面信息呈现看不到太大延迟,感觉很好.