简介
DWR(Direct Web Remoting)是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架,可以帮助开发人员开发包含AJAX技术的网站。它可以允许在浏览器里的代码使用运行在WEB服务器上的JAVA方法,就像它就在浏览器里一样。
示例
[springMVC+dwr3 实现精确推送信息(2种方法)]:https://blog.csdn.net/threesan333/article/details/12502689
[三种推送方式]: https://blog.csdn.net/yxpjx/article/details/5004812
注意:DWR默认采用piggyback被动推送
的推送方式,在Windows环境下能够即时接收;但在Linux环境中,并不生效。针对Linux下服务器不推送的情况需采用polling轮询推送
。
项目示例
需求介绍
公司有个功能叫做出入室管理,类似大厦进出登记一样,前台提供身份证识别机器,用户刷身份证登记之后(服务器自动查询该人员是否能够入室)如果存在入室清单中,前台浏览器界面自动弹出该人员入室登记信息,填写入室门禁卡号码之后将卡还有签字板提供入室人员签字,人员签字确认之后,由前台点击完成入室操作。
该功能需对接两个硬件厂商,分别是身份证读卡器以及签字板,对接过程的省略。直接说读取身份证之后自动弹出入室人员界面,这里需要运用服务器主动推送信息并打开页面。推送的框架有比较旧的DWR、GoEasy、WebSocket等。但由于项目框架版本低且不在支持的应用服务器之内,只能选择网上流传过时的DWR。
首先引入dwr jar
包:
<!-- DWR -->
<dependency>
<groupId>org.directwebremoting</groupId>
<artifactId>dwr</artifactId>
<version>3.0.2-RELEASE</version>
</dependency>
web.xml
加入DWR配置
<!-- 配置DWR的核心Servlet -->
<servlet>
<display-name>DWR Servlet</display-name>
<!-- 指定DWR核心Servlet的名字 -->
<servlet-name>dwr-invoker</servlet-name>
<!-- 指定DWR核心Servlet的实现类 -->
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<!-- 指定DWR核心Servlet处于调试状态 -->
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
<!-- 使用服务器反转AJAX -->
<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>
<!-- 是能够从其他域请求true:开启; false:关闭 -->
<init-param>
<param-name>crossDomainSessionSecurity</param-name>
<param-value>true</param-value>
</init-param>
<!-- 允许远程调用js -->
<init-param>
<param-name>allowScriptTagRemoting</param-name>
<param-value>true</param-value>
</init-param>
<!-- 针对Linux下服务器不推送的情况。详见:https://blog.csdn.net/yxpjx/article/details/5004812 -->
<!-- 默认方式:piggyback(被动模式); -->
<init-param>
<param-name>org.directwebremoting.extend.ScriptSessionManager</param-name>
<param-value>com.ccssoft.rsas.bjflow.idcpersonentry.service.DwrScriptSessionManagerUtil</param-value>
</init-param>
<init-param>
<param-name>org.directwebremoting.extend.ServerLoadMonitor</param-name>
<param-value>org.directwebremoting.impl.PollingServerLoadMonitor</param-value>
</init-param>
<!-- 反转Ajax间隔:默认5毫秒,看源码所得。http://localhost:9090/dwr/call/plainpoll/ReverseAjax.dwr -->
<!--
<init-param>
<param-name>disconnectedTime</param-name>
<param-value>5000</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>
WEB-INF
下新建dwr.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN"
"http://getahead.org/dwr/dwr30.dtd">
<dwr>
<allow>
</allow>
</dwr>
创建类DwrScriptSessionManagerUtil
package com.ccssoft.rsas.bjflow.idcpersonentry.service;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import org.directwebremoting.ScriptSession;
import org.directwebremoting.WebContextFactory;
import org.directwebremoting.event.ScriptSessionEvent;
import org.directwebremoting.event.ScriptSessionListener;
import org.directwebremoting.impl.DefaultScriptSession;
import org.directwebremoting.impl.DefaultScriptSessionManager;
import com.regaltec.baf.org.user.common.valueobj.UserVO;
import com.regaltec.baf.org.user.ui.control.UserLoginBean;
public class DwrScriptSessionManagerUtil extends DefaultScriptSessionManager {
/**
* 日志对象
*/
protected Logger logger = Logger.getLogger(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();
// 当前登录对象
UserLoginBean loginBean = (UserLoginBean) httpSession
.getAttribute("userLoginBean");
UserVO userVO = null;
String userId = null;
if (loginBean != null) {
userVO = loginBean.getCurrentUser();
userId = userVO.getUserId();
}
// 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);
}
MessagePush
推送的类:
package com.ccssoft.rsas.bjflow.idcpersonentry.service;
import java.util.Collection;
import org.apache.log4j.Logger;
import org.directwebremoting.Browser;
import org.directwebremoting.ScriptBuffer;
import org.directwebremoting.ScriptSession;
import org.directwebremoting.ScriptSessionFilter;
import com.ccssoft.rsas.bjflow.idcpersonentry.entity.Person;
public class MessagePush {
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);
}
}
});
}
/**
* 入室
* @param userid 用户id
* @param person 入室人员,如果为null表示不可入室
* @param message 后台匹配处理返回的消息
*/
public static void sendPersonAuto(String userid, final Person person, String message) {
final String userId = userid;
final String autoMessage = message;
final String OP_ID = "userId";
long currentTimeMillis = System.currentTimeMillis();
System.out.println("开始1:"+currentTimeMillis);
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);
String info = null;
if(person != null) {
info = person.getId()+","+person.getPerstatus()+","+person.getAreaname();
}
script.appendCall("showMessage", info, autoMessage);
Collection<ScriptSession> sessions = Browser.getTargetSessions();
for (ScriptSession scriptSession : sessions) {
scriptSession.addScript(script);
}
}
});
System.out.println("结束1:"+System.currentTimeMillis());
System.out.println("耗时1: "+(System.currentTimeMillis() -currentTimeMillis ));
}
}
前端部分:
<script type="text/javascript" src="${pageContext.request.contextPath }/dwr/engine.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/dwr/util.js"></script>
function showMessage(info, autoMessage){
//alert(person+"==="+dwr.util.toDescriptiveString(autoMessage));
if(info == null){
tip(autoMessage);// 提示内容
return;
}
//alert(info);
enter(info);// 自动打开窗口操作
}
function enter(info) {
var infos = info.split(',');
var queryParams = {
'pid' : infos[0],
'perstatus':infos[1],
'areaname':infos[2]
};
personEnterroomDialog = add(datagrid, '详情信息', toShowEnterroomUrl, queryParams);
}
调用过程
// 推送
Person person = new Person();
// 身份证
person.setCertname("1");
// 身份证号
// 测试推送
idNum = "110107198904051516";
person.setCertnumber(idNum);
// IDC中心
person.setIdcs(idcs);
Page<Person> page = new Page<Person>();
page = idcEntryService.findPersonInfo(new Page<Person>(new DataGrid()), person, null, preCurrentUser);
String message = "该人员不可入室";
if(page.getCount() > 0) {
person = page.getList().get(0);
String id = person.getId();
String perstatus = person.getPerstatus();
String areaname = person.getAreaname();
logger.info("开始进入入室页面:"+ id+", "+perstatus+", "+areaname);
message = "入室操作";
}
else {
person = null;
}
MessagePush.sendPersonAuto(userId, person, message);