DWR3 逆向ajax 推送消息到指定用户界面

DWR(Direct Web Remoting)是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,可以帮助开发人员开发包含AJAX技术的网站。它可以允许在浏览器里的代码使用运行在WEB服务器上的JAVA方法,就像它就在浏览器里一样。

DWR采取了一个类似AJAX的新方法来动态生成基于JAVA类的JavaScript代码。这样WEB开发人员就可以在JavaScript里使用Java代码,就像它们是浏览器的本地代码(客户端代码)一样;但是Java代码运行在WEB服务器端而且可以自由访问WEB 服务器的资源。出于安全的理由,WEB开发者必须适当地配置哪些Java类可以安全的被外部使用。 

DWR Reverse Ajax(逆向Ajax)主要是在BS架构中,从服务器端向多个浏览器主动推数据的一种技术。 

 

项目使用的maven搭建,以下写具体搭建dwr框架步骤:

1、pom.xml加入配置:

<dependency>
			<groupId>org.directwebremoting</groupId>
			<artifactId>dwr</artifactId>
			<version>3.0.2-RELEASE</version>
</dependency>

2、web.xml加入配置信息:

 <servlet>  
		  <servlet-name>dwrServlet</servlet-name>  
		  <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>  
		  <init-param>  
		    <param-name>debug</param-name>  
		    <param-value>false</param-value>  
		  </init-param>  
		  <init-param>  
		    <param-name>activeReverseAjaxEnabled</param-name>  
		    <param-value>true</param-value>  
		  </init-param>  
		  <init-param>  
		    <param-name>pollAndCometEnabled</param-name>  
		    <param-value>true</param-value>  
		  </init-param>  
		  <init-param>  
		  <!-- 不允许跨域 -->
		    <param-name>crossDomainSessionSecurity</param-name>  
		    <param-value>false</param-value>  
		  </init-param>  
		  <init-param>  
		    <param-name>allowScriptTagRemoting</param-name>  
		    <param-value>true</param-value>  
		  </init-param>  
		  <load-on-startup>1</load-on-startup>  
     </servlet>  
	<servlet-mapping>  
	  <servlet-name>dwrServlet</servlet-name>  
	  <url-pattern>/dwr/*</url-pattern>  
	</servlet-mapping>  

3、增加dwr.xml文件,这里与web.xml同级,内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<dwr>  

    <allow>  

        <create javascript="MessageService" creator="new">  

            <param name="class" value="service.DwrMessageService"></param>  

            <include method="onPageLoad"/>

        </create>  

    </allow>  

</dwr> 

include指定了只能调用该类中的哪个方法,MessageService为前面页面引用时的名称

4、新建DwrMessageService类如下:


public class DwrMessageService {
	public void onPageLoad(String userId) {
		// TODO Auto-generated method stub
		ScriptSession scriptSession = WebContextFactory.get().getScriptSession();

		scriptSession.setAttribute("userId", userId);

		DwrScriptSessionManager dwrScriptSessionManagerUtil = new DwrScriptSessionManager();

		try {

			dwrScriptSessionManagerUtil.init();

		} catch (ServletException e) {

			e.printStackTrace();

		}
	}

	private class DwrScriptSessionManager extends DwrServlet{
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public void init() throws ServletException {

			Container container = ServerContextFactory.get().getContainer();

			ScriptSessionManager manager = container.getBean(ScriptSessionManager.class);

			ScriptSessionListener listener = new ScriptSessionListener() {

				public void sessionCreated(ScriptSessionEvent ev) {

					HttpSession session = WebContextFactory.get().getSession();

					String userId = (String) session.getAttribute("userId");


					ev.getSession().setAttribute("userId", userId);

				}

				public void sessionDestroyed(ScriptSessionEvent ev) {

				//	System.out.println(">>>>>>>>a ScriptSession is distroyed");

				}

			};
			manager.addScriptSessionListener(listener);

		}
		
	}
}

5、建立消息发送类SendDwrMsg,这里使用了静态内部内实现的单例模式,详细不说了,看代码 :

public class SendDwrMsg {
	
	private static class SendDwrMsgHolder{
		private static final SendDwrMsg instance=new SendDwrMsg();
	}
	public static SendDwrMsg getInstance() {
		return SendDwrMsgHolder.instance;
	}
	
	 public   void sendMessageAuto(String userid, String message){  
         
	        final String userId = userid;  
	        final String autoMessage = message;  
	        Browser.withAllSessionsFiltered(new ScriptSessionFilter() {  
	            public boolean match(ScriptSession session){  
	                if (session.getAttribute("userId") == null)  
	                    return false;  
	                else  
	                    return (session.getAttribute("userId")).equals(userId);  
	            }  
	        }, new Runnable(){  
	              
	            private ScriptBuffer script = new ScriptBuffer();  
	              
	            public void run(){  
//这里showMessage为前端接收消息的js方法名
	                  
	                script.appendCall("showMessage", autoMessage);  
	                  
	                Collection<ScriptSession> sessions = Browser  
	  
	                .getTargetSessions();  
	                  
	                for (ScriptSession scriptSession : sessions){  
	                    scriptSession.addScript(script);  
	                }  
	            }  
	        });  
	    }
	
}

到此dwr相关配置完成,下面说实际使用。

jsp页面中引入dwr的engine.js 、util.js 以及新建的初始化类的js,详细如下

  <script type='text/javascript' src='${pageContext.request.contextPath}/dwr/engine.js'></script>  
  <script type='text/javascript' src='${pageContext.request.contextPath}/dwr/util.js'></script>  
  <script type="text/javascript" src="${pageContext.request.contextPath}/dwr/interface/MessageService.js"></script>  

 调用MessageService中的onPageLoad方法:

	    dwr.engine._errorHandler = function(message, ex) {
		dwr.engine._debug("Error: " + ex.name + ", " + ex.message, true);
		};
//设置engine的errorHandler是为了防止浏览器弹出incomplete reply from server 错误
	var initFlag=false;
	  function onPageLoad(){ 
          if(!initFlag){
          MessageService.onPageLoad(${initId});  
          dwr.engine.setActiveReverseAjax(true);dwr.engine.setNotifyServerOnPageUnload(true);
          flag=true;
          }
        }
	//推送信息  
      function showMessage(autoMessage){  
    	 	console.log(autoMessage);
     }

由于本测试为同一个页面推送及接收消息。为了防止重复初始化,加入initFlag标记,为使用能够达到精确推送的目的,而实际应用时用户可以多次登录,为此在后端以一定 的规则生成 了initId,每次访问这个页面时,后端都将生成一个initId用于唯一标识页面。

必须设置:          dwr.engine.setActiveReverseAjax(true);dwr.engine.setNotifyServerOnPageUnload(true);  启动该页面的Reverse Ajax功能否则无法接收到消息

到此配置完成 。。

 

由于实际使用中应用使用了nginx做负载均衡,当把此项目部署后发现消息推送总是会出现延迟的情况,直接访问当前应用服务器又正常,推断应该是由nginx造成。在nginx配置文件中增加proxy_buffering off; 推送正常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值