springMVC+dwr3 实现精确推送信息(2种方法)

springMVC+dwr3  实现消息精确推送(注解方式+文件方式)

本文假定以完成springMVC配置,并且涉及配置都是在springMVC配置之上添加。由于现在对其中的一些原理还不是很理解,所以对于每一个的配置的不会解释为什么这样做

dwr3是从dwr官网上下载最新的。http://directwebremoting.org/dwr/index.html

方法 1:(此方法可能在第一个打开页面是不能推送消息,原因不明)

文件方式:

1A、在web.xml里面加入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>
  <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>dwr-invoker</servlet-name>
  <url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
1B、在web.xml同级目录下建立dwr.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
    "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN"
    "http://directwebremoting.org/schema/dwr30.dtd">
<dwr>
	<allow>
		<create javascript="MessagePush" creator="new">
			<param name="class" value="com.arch.web.dwr.MessagePush"></param>
		</create>
	</allow>
</dwr>
其中  com.arch.web.dwr.MessagePush,就是我的消息推送注册类。

1C、建立MessgePush类,具体类内容如下

public class MessagePush {

	public void onPageLoad(String userId) {

		ScriptSession scriptSession = WebContextFactory.get().getScriptSession();

		scriptSession.setAttribute(userId, userId);

		DwrScriptSessionManagerUtil dwrScriptSessionManagerUtil = new DwrScriptSessionManagerUtil();

		try {

			dwrScriptSessionManagerUtil.init();

		} catch (ServletException e) {

			e.printStackTrace();

		}

	}
}
开放onPageLoad方法供前段页面注册调用

1D、MessagePush需要DwrScriptSessionManagerUtil,建立DwrScriptSessionManagerUtil 内容如下:

public class DwrScriptSessionManagerUtil extends DwrServlet {

	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");

				System.out.println("a ScriptSession is created!");

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

			}

			public void sessionDestroyed(ScriptSessionEvent ev) {

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

			}

		};

		manager.addScriptSessionListener(listener);

	}
}

1E、前段页面

引入dwr核心js

<script type="text/javascript" src="<%=basePath%>dwr/engine.js"></script> <!-- basePath:网站基本路基-->
<script type="text/javascript" src="<%=basePath%>dwr/util.js"></script>

引入消息注册js

<script type="text/javascript" src="<%=basePath%>dwr/interface/callTest.js"></script>

建立注册js和接受消息js

function onPageLoad(){
	var userId = '${userId}';
	MessagePush.onPageLoad(userId);
}

function showMessage(msg) {
	alert(dwr.util.toDescriptiveString(data)); 
}

在页面body标签中加入onload属性信息

<body οnlοad="dwr.engine.setActiveReverseAjax(true);dwr.engine.setNotifyServerOnPageUnload(true);onPageLoad();">

1F、现在需要一个推送消息方法来向特定用户发送我们的推送消息(随便放入一个类中都可以)

public static void sendMessageAuto(String userid, String message) {

		final String userId = userid;

		final String autoMessage = message;
		final String OP_ID = "userId";
		
		Browser.withAllSessionsFiltered(new ScriptSessionFilter() {

			public boolean match(ScriptSession session) {
				if (session.getAttribute(OP_ID) == null)
					return false;
				else {
					boolean f = session.getAttribute(OP_ID).equals(userId);
					return f;
				}
			}

		}, new Runnable() {

			private ScriptBuffer script = new ScriptBuffer();

			public void run() {

				script.appendCall("showMessage", autoMessage);
				Collection<ScriptSession> sessions = Browser.getTargetSessions();
				for (ScriptSession scriptSession : sessions) {
					scriptSession.addScript(script);
				}

			}

		});

	}
以上是全部配置,现在就可以使用sendMessageAuto向指定用户推送消息

     注解方式:

注解方式其实和文件方式类似;需要修改的地方如下:

1、在(1A)步中,不再web.xml里面配置dwr,而是在springMVC文件中配置dwr,具体配置如下

	<!-- DWR配置 -->
	<bean  class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
	<dwr:annotation-scan base-package="com.cb" scanDataTransferObject="true"/>
	<dwr:configuration />
	<dwr:annotation-config id="dwr"/>
	<dwr:url-mapping />
	<dwr:controller id="dwrController" debug="true">
		<dwr:config-param name="allowScriptTagRemoting"
			value="true" />
		<dwr:config-param name="crossDomainSessionSecurity"
			value="false" />
		<dwr:config-param name="activeReverseAjaxEnabled"
			value="true" />
		<dwr:config-param name="pollAndCometEnabled"
			value="true" />
		<dwr:config-param name="allowScriptTagRemoting"
			value="true" />
	</dwr:controller>
	
	<bean
		class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
		<property name="order" value="1" />
	</bean>
   <bean
        class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
        <property name="order" value="2" />
    </bean>
	<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="order" value="3" />
		<property value="true" name="alwaysUseFullPath"></property>
		<property name="mappings">
			<props>
				<prop key="/dwr/**">dwrController</prop>
			</props>
		</property>
	</bean>
2、不需要dwr.xml配置文件,省略( 1B)步

3、在(1D)步中,向MessagePush类中加入注解

@RemoteProxy(name="MessagePush")
public class MessagePush {

	@RemoteMethod
	public void onPageLoad(String userId) {

		ScriptSession scriptSession = WebContextFactory.get().getScriptSession();

		scriptSession.setAttribute(userId, userId);

		DwrScriptSessionManagerUtil dwrScriptSessionManagerUtil = new DwrScriptSessionManagerUtil();

		try {

			dwrScriptSessionManagerUtil.init();

		} catch (ServletException e) {

			e.printStackTrace();

		}

	}
}
其他不变。

注:此种方法有可能在首次打开页面的时候不能创建session,导致不能推送消息,但是页面刷新一下就好了。(为什么会这样具体原因还没有找到哭


方法2:

为了解决方法1中出现的首次打开可能不能推送问题,这里的做法是在每次用户打开需要推送的页面时自动创建scriptSession,并且只要假定只要使用了dwr页面都需要推送(当然这个是可以根据自己的业务修改规则,实现特定页面精确推送)

文件方式:

2A、首先需要创建自己的session管理类,这里的名称为:com.toolbox.util.DwrScriptSessionManagerUtil

public class DwrScriptSessionManagerUtil extends DefaultScriptSessionManager{ 
	

	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	private static final String SS_ID = "DWR_ScriptSession_Id";
	private static final String OP_ID = "userId";

	
	public DwrScriptSessionManagerUtil(){
		addScriptSessionListener(new ScriptSessionListener() {
	    	  public void sessionCreated(ScriptSessionEvent ev) {
	    		    logger.info(" script session in.....");
	    		 
                    HttpSession httpSession = WebContextFactory.get().getSession();
                    ScriptSession scriptSession = ev.getSession();
                    
                    String userId = (String)httpSession.getAttribute("userId");
					if (userId == null) {
						logger.info(" script session invalidate");
						scriptSession.invalidate();
						httpSession.invalidate();
						return;
					}
					//已经存在旧的scriptSession 注销这个旧的scriptSession
					DefaultScriptSession old = sessionMap.get(userId);
					if (old != null){
						DwrScriptSessionManagerUtil.this.invalidate(old);
					}
					
					httpSession.setAttribute(SS_ID, scriptSession.getId());

					scriptSession.setAttribute(OP_ID, userId);
					scriptSession.setAttribute("SESSIONID", httpSession.getId());
					logger.info(" script session created: " + userId);
	             }
	    	  
	             public void sessionDestroyed(ScriptSessionEvent ev) {
	          		ScriptSession ss = ev.getSession();
	  				if (ss.getAttribute(OP_ID) != null){
	  					logger.info(" script session destroyed: " + ss.getAttribute(OP_ID));
	  				}
	             }
	      });
		
		//this.setScriptSessionTimeout(150000L);
	}
2B、将我们的session管理类加入dwr控制器中

<servlet>
  <servlet-name>dwr-invoker</servlet-name>
  <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
  <init-param>
	<param-name>org.directwebremoting.extend.ScriptSessionManager</param-name>
	<param-value>com.toolbox.util.DwrScriptSessionManagerUtil</param-value>
  </init-param>

  <init-param>
    <param-name>debug</param-name>
    <param-value>true</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>dwr-invoker</servlet-name>
  <url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
2C、在web.xnl同目录下建立一个空的dwr.xnl文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
    "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN"
    "http://directwebremoting.org/schema/dwr30.dtd">
<dwr>
	<allow>
	</allow>
</dwr>
2D、前端页面

<script type="text/javascript" src="<%=basePath%>dwr/engine.js"></script> <!-- basePath:网站基本路基-->
<script type="text/javascript" src="<%=basePath%>dwr/util.js"></script>
function showMessage(msg) {
	alert(dwr.util.toDescriptiveString(data)); 
}
<body οnlοad="dwr.engine.setActiveReverseAjax(true);dwr.engine.setNotifyServerOnPageUnload(true);">
这里因为后端假定只要使用了dwr就会需要推送消息,所以钱端不需要调用消息注册操作

2E、消息发送方法

public static void sendMessageAuto(String userid, String message) {

		final String userId = userid;

		final String autoMessage = message;
		final String OP_ID = "userId";
		
		Browser.withAllSessionsFiltered(new ScriptSessionFilter() {

			public boolean match(ScriptSession session) {
				if (session.getAttribute(OP_ID) == null)
					return false;
				else {
					boolean f = session.getAttribute(OP_ID).equals(userId);
					return f;
				}
			}

		}, new Runnable() {

			private ScriptBuffer script = new ScriptBuffer();

			public void run() {

				script.appendCall("showMessage", autoMessage);
				Collection<ScriptSession> sessions = Browser.getTargetSessions();
				for (ScriptSession scriptSession : sessions) {
					scriptSession.addScript(script);
				}

			}

		});

	}
到这里全部都完了。现在前段能正常接收到推送消息

注解方式:

这里的注解方式就方便很多了,和《方法1》中类似需要改变的步骤有:

· 1、(2B) 中不需要在web.xml中配置dwr,dwr配置在springMVC中

<bean  class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
	<dwr:annotation-scan base-package="com.cb" scanDataTransferObject="true"/>
	<dwr:configuration />
	<dwr:annotation-config id="dwr"/>
	<dwr:url-mapping />
	<dwr:controller id="dwrController" debug="true">
		<dwr:config-param name="allowScriptTagRemoting"
			value="true" />
		<dwr:config-param name="crossDomainSessionSecurity"
			value="false" />
		<dwr:config-param name="activeReverseAjaxEnabled"
			value="true" />
		<dwr:config-param name="org.directwebremoting.extend.ScriptSessionManager"
			value="com.toolbox.util.DwrScriptSessionManagerUtil" />
		<dwr:config-param name="pollAndCometEnabled"
			value="true" />
		<dwr:config-param name="allowScriptTagRemoting"
			value="true" />
	</dwr:controller>
	
	<bean
		class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
		<property name="interceptors">
			<list>
				<bean class="com.arch.interceptor.AclInterceptorAdapter" />
			</list>
		</property>
		<property name="order" value="1" />
	</bean>
   <bean
        class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
        <property name="order" value="2" />
    </bean>
	<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="order" value="3" />
		<property value="true" name="alwaysUseFullPath"></property>
		<property name="mappings">
			<props>
				<prop key="/dwr/**">dwrController</prop>
			</props>
		</property>
	</bean>

2、不要dwr.xml配置文件,所以跳过 (2C)

其他步骤不变。

这样dwr3消息推送搭建完成。

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值