DWR允许客户端脚本远程调用服务器端的类方法。使用它可以很容易的构建ajax程序。在此,简要说明一下如何通过DWR构建一个简单的一对一聊天程序。
1.首先配置web.xml
<!-- 配置spring --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置DwrServlet --> <display-name>DWR (Direct Web Remoting)</display-name> <description>A Simple Demo DWR</description> <servlet> <servlet-name>dwr-invoker</servlet-name> <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class> <init-param><!--开启debug为true后,可以通过访问ContextPath/dwr/index.html进行调试--> <param-name>debug</param-name> <param-value>true</param-value> </init-param> <init-param><!--该选项为true时,轮询和反向ajax会被启用--> <param-name>activeReverseAjaxEnabled</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>initApplicationScopeCreatorsAtStartup</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>maxWaitAfterWrite</param-name> <param-value>-1</param-value> </init-param> <init-param><!--该参数为true时,允许远程服务器将javascript代码动态添加到客户端页面中--> <param-name>allowScriptTagRemoting</param-name> <param-value>true</param-value> </init-param> <load-on-startup>3</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> <!-- 监听scriptSession --> <servlet> <servlet-name>scriptSessionListener</servlet-name> <servlet-class>com.hb.util.InitScriptSessionListener</servlet-class> <load-on-startup>8</load-on-startup> </servlet>
2.配置dwr.xml
<create creator="spring" javascript="MessageService" scope="application"> <param name="beanName" value="dwrMessageService"/> </create> <convert converter="bean" match="com.entity.Message" />
dwr中create元素中creator属性为spring,表示,名为“dwrMessageService”的bean由spring进行管理,javascript属性值表示如何在客户端调用该bean,即通过该属性的值调用。dwr可以自动对javascript对象和java对象进行转化。convert元素的match属性即表示哪个java bean交由dwr进行互转。
3.spring配置文件如下
<bean id="dwrMessageService" class="com.dwr.MyMessageService" scope="prototype"> <property name="messageService"> <ref bean="messageService"/> </property> </bean>
4.(1)com.dwr.MyMessageService类部分代码如下:
import com.util.initParam; public boolean pushMessageToSomeOne(String userId,Message msg){ /*将消息保存到数据库*/ try { messageService.saveMessage(msg); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } //调用接收方客户端的showMessageFromOne(msg)函数,将msg消息传递给接收方 ScriptBuffer script = new ScriptBuffer(); script.appendScript("showMessageFromOne("). appendData(msg).appendScript(");"); ScriptSession s1= initParam.sc.get(userId); //获取接收方的ScriptSession s1.addScript(script); return true; }
(2)com.util.initParam类
package com.util; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.directwebremoting.ScriptSession; import com.dwr.ScriptSessionAndUser; public class initParam { public static Map<String,ScriptSession> sc =newHashMap<String,ScriptSession>(); // 保存用户id和该用户对应的ScriptSession public initParam(){} }
(3)用来监听ScriptSession的Servlet:InitScriptSessionListener
package com.util; import java.io.IOException; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpSession; import org.directwebremoting.Container; import org.directwebremoting.ScriptSession; import org.directwebremoting.ServerContextFactory; import org.directwebremoting.WebContextFactory; import org.directwebremoting.event.ScriptSessionEvent; import org.directwebremoting.event.ScriptSessionListener; import org.directwebremoting.extend.ScriptSessionManager; public class InitScriptSessionListener extends GenericServlet { /* 监控ScriptSessionListener状态*/ public void init() { Container container = ServerContextFactory.get().getContainer(); ScriptSessionManager manager =container.getBean(ScriptSessionManager.class); ScriptSessionListener listener = new AddScriptSessionListener(); manager.addScriptSessionListener(listener); } @Override public void service(ServletRequest arg0,ServletResponse arg1) throws ServletException,IOException { // TODO Auto-generated method stub init(); } }
(4)AddScriptSessionListener类
package com.util; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpSession; import org.directwebremoting.ScriptSession; import org.directwebremoting.WebContext; import org.directwebremoting.WebContextFactory; import org.directwebremoting.event.ScriptSessionEvent; import org.directwebremoting.event.ScriptSessionListener; public class AddScriptSessionListener implements ScriptSessionListener{ public void sessionCreated(ScriptSessionEvent se) { /*客户端刷新页面后,将用户的session信息和ScriptSession重新绑定*/ WebContext ct = WebContextFactory.get(); HttpSession session =ct.getHttpServletRequest().getSession(); initParam.sc.put(session.getAttribute("UsersId").toString(),se.getSession()); public void sessionDestroyed(ScriptSessionEvent se) { System.out.println(se.getSession()+"销毁"); } }
5.客户端代码
<script type="text/javascript" src=\'#\'" /engine.js"</script> <script type="text/javascript" src=\'#\'" /interface/MessageService.js"></script> <script type="text/javascript"> dwr.engine.setActiveReverseAjax(true); //启用dwr反向ajax dwr.engine.setNotifyServerOnPageUnload(true);//刷新页面后销毁当前scriptsession dwr.engine.setErrorHandler(function() { //alert("错误"); }); //自定义错误处理方式 function sendMessageTo(userId) { var content=document.getElementById("content").innerHTML; document.getElementById("content").innerHTML=""; document.getElementById("message").innerHTML=getId("message").innerHTML+"<li><span>${session.username}"+content+"</span></li>"; var msg={}; msg.getId=userId; msg.content=content; msg.sendId=${session.userId};//将发送的信息显示到信息框 MessageService.pushMessageToSomeOne(userId,msg,function(data){}); //通过MessageService对象调用远程MyMessageService类的 public boolean pushMessageToSomeOne(String userId,Message msg)方法,最后一个参数为回调函数 } function showMessageFromOne(msg) { var htmls="<li><span>"+msg.sendId+"+msg.content+"</span></li>"; document.getElementById("message").innerHTML=document.getElementById("message").innerHTML+htmls+"<br />"; } }
<script type="text/javascript" src=\'#\'" /engine.js"</script> <script type="text/javascript" src=\'#\'" /interface/MessageService.js"></script> <script type="text/javascript"> dwr.engine.setActiveReverseAjax(true); //启用dwr反向ajax dwr.engine.setNotifyServerOnPageUnload(true);//刷新页面后销毁当前scriptsession dwr.engine.setErrorHandler(function() { //alert("错误"); }); //自定义错误处理方式 function sendMessageTo(userId) { var content=document.getElementById("content").innerHTML; document.getElementById("content").innerHTML=""; document.getElementById("message").innerHTML=getId("message").innerHTML+"<li><span>${session.username}"+content+"</span></li>"; var msg={}; msg.getId=userId; msg.content=content; msg.sendId=${session.userId};//将发送的信息显示到信息框 MessageService.pushMessageToSomeOne(userId,Message msg)方法,最后一个参数为回调函数 } }
<div id="container"> <div id="message"></div> <div id="content"></div> <input type="button" data-role="button" onclick="sendMessageTo(${getUsers.id})">发送</a> </div>
6.现在解释一下ScriptSession.我们知道,一般的Session会在用户初次访问时创建,然后在用户的整个访问过程中一直存在,直到用户在一定时间内未进行任何访问后销毁。 而DWR中的ScriptSession则是用户每次刷新或重新请求一个dwr控制的页面时,重新创建。因此,在本例中我们创建了ScriptSession的监听器,每当重新创建新的ScriptSession时,将当前用户的session与新的ScriptSession重新绑定,以便可以确切的将消息发送给目标用户,而不是调用一个已经不存在的ScriptSession。 通过在页面加载后调用dwr.engine.setNotifyServerOnPageUnload(true);可以使DWR在创建一个新的ScriptSession后自动销毁之前的ScriptSession。
7.本例是本人在测试的项目当中挖取的一部分主要内容,可能不够全面,也存在一些问题。望大家批评指正。谢谢。