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加入配置:


			org.directwebremoting
			dwr
			3.0.2-RELEASE

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

   
		  dwrServlet  
		  org.directwebremoting.servlet.DwrServlet  
		    
		    debug  
		    false  
		    
		    
		    activeReverseAjaxEnabled  
		    true  
		    
		    
		    pollAndCometEnabled  
		    true  
		    
		    
		  
		    crossDomainSessionSecurity  
		    false  
		    
		    
		    allowScriptTagRemoting  
		    true  
		    
		  1  
       
	  
	  dwrServlet  
	  /dwr/*  
	  

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



  

      

          

              

            

          

      

 

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 sessions = Browser  
	  
	                .getTargetSessions();  
	                  
	                for (ScriptSession scriptSession : sessions){  
	                    scriptSession.addScript(script);  
	                }  
	            }  
	        });  
	    }
	
}

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

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

    
    
    

 调用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; 推送正常

你可能感兴趣的:(软件架构)