dwr实现web单聊

2024-05-05 02:38
文章标签 实现 web dwr 单聊

本文主要是介绍dwr实现web单聊,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

通过DWR实现单对单聊天,参考网络技术文章资料,非常感谢具有分享精神的技术大牛们,结合资料,做了以下技术总结:

1、下载dwr.jar

官网地址:http://directwebremoting.org/dwr/downloads/ 

下载最新版本V3.0

dwr.jar依赖commons-logging.jar,下载commons-logging.jar

2、导入jar

         将上述下载的jar 复制到web工程的WEB-INF/lib 下

3、在web.xml中加入dwr的servlet和相关配置

<!-- DWR配置 START --><servlet><servlet-name>DWRServlet</servlet-name><servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class><!-- comet方式 --><init-param><param-name>activeReverseAjaxEnabled</param-name><param-value>true</param-value></init-param><!-- polling方式:在comet方式的基础之上,再配置以下参数 --><init-param>  <param-name>org.directwebremoting.extend.ServerLoadMonitor</param-name>  <param-value>org.directwebremoting.impl.PollingServerLoadMonitor</param-value>  </init-param> <init-param><param-name>debug</param-name><param-value>false</param-value></init-param><!-- 毫秒数。页面默认的请求间隔时间是5秒 --><init-param><param-name>disconnectedTime</param-name><param-value>5000</param-value> </init-param>		<!-- 指定配置文件 --><init-param><param-name>config</param-name><!-- 如果有多个用","分开 --><param-value>/WEB-INF/classes/dwr.xml                </param-value></init-param><!-- dwr的comet控制 --><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><!-- 安全设置,允许远程js --><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> <servlet> <servlet-name>messageutil</servlet-name><servlet-class>com.dc.platform.action.DwrScriptSessionManagerUtil</servlet-class><load-on-startup>2</load-on-startup></servlet>	<!-- DWR配置 END -->

4DwrScriptSessionManagerUtil.java配置

/*** @description :在线用户链接监听*/
public class DwrScriptSessionManagerUtil extends DwrServlet{private static final long serialVersionUID = -7504612622407420071L;private OnlineUserService onlineUserService;public void init() throws ServletException {<span style="white-space:pre">	</span>onlineUserService = (OnlineUserService)Context.getBean("onlineUserService");ServerContext serverContext = ServerContextFactory.get();Container container = serverContext.getContainer();ScriptSessionManager manager = container.getBean(ScriptSessionManager.class);ScriptSessionListener listener = new ScriptSessionListener() {//销毁sessionpublic void sessionDestroyed(ScriptSessionEvent event) {int userId = Integer.parseInt((String)event.getSession().getAttribute("userId"));onlineUserService.removeScriptSession(userId);}//创建sessionpublic void sessionCreated(ScriptSessionEvent event) {HttpSession session = WebContextFactory.get().getSession();User user = (User)session.getAttribute("login");user.setScriptSession(event.getSession());onlineUserService.addScriptSession(user);event.getSession().setAttribute("userId", user.getId()+"");}};// 设置监听,dwr3才有manager.addScriptSessionListener(listener);SessionContainer.container.setManager(manager);}
}

5、

调用有简单返回值的

java

方法

 

调用有简单返回值的java方法  dwr.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://getahead.org/dwr/dwr30.dtd">
<!-- 通用dwr配置 -->
<dwr><allow><!-- 从Spring中获取Java对象 --><create javascript="chatRoomService" creator="spring"><param name="beanName" value="chatRoomService"></param></create></allow>
</dwr>

6、页面引用以下js

<!--dwr相关  -->
<script type='text/javascript' src='dwr/engine.js'></script>
<script type='text/javascript' src='dwr/util.js'></script>
<script type='text/javascript' src='dwr/interface/chatRoomService.js'></script>  //自定义的service类方法

dwr/engine.js,dwr/util.js是固定的,是Dwr的脚本驱动Js和常用的工具类用来对返回的信息加工处理的。
dwr/interface/chatRoomService.js是用户需要直接访问的JavaBean对应的JavaScript映射。注意路径
的书写,以及相对位置,这几个文件的层次结构是固定的。并且应用在部署的时候要选择Root方式,否则找不到路径。

7、index.jsp注册当前在线人员 

$(function(){  dwr.engine.setActiveReverseAjax(true);dwr.engine.setNotifyServerOnPageUnload(true);chatRoomService.addScriptSession($("#username").val(),$("#userid").val(),function(msg){
// 		alert("登录系统");});
});

注意:    dwr.engine.setActiveReverseAjax(true);
dwr.engine.setNotifyServerOnPageUnload(true);

这个是要在使用reverse-ajax的页面必须的

8、后台service处理注册人员

/** * 添加客户端session将跳转放置dwr的回调函数中 * 登录成功后进行调用  * @param username* @param req* @return*/
public String addScriptSession(String userid, HttpServletRequest req) {  //此方法定义为上线注册,并更新所有人的在线人员列表Browser.withAllSessions(new Runnable() {private ScriptBuffer script = new ScriptBuffer();@Overridepublic void run() {Collection<ScriptSession> sessions =  Browser.getTargetSessions();Set<String> sessionUserIds = new HashSet<String>();//循环所有在线者,因一个人会有多个ScriptSession,去重String userIdStr="";for (ScriptSession scriptSession : sessions) {String sessionUserId = (String) scriptSession.getAttribute("userId");if(!sessionUserIds.contains(sessionUserId)){sessionUserIds.add(sessionUserId);userIdStr += sessionUserId + ",";}}if(userIdStr.endsWith(",")){userIdStr = userIdStr.substring(0, userIdStr.length()-1);}int sessionUserCount=0;sessionUserCount=sessionUserIds.size();String sql="select id,name from sys_user where id in ("+userIdStr+") order by sortcol asc";SEntityList userlist = baseDao.search(sql, null);String onlineusers = "";for (SEntity user : userlist) {onlineusers += "<a οnclick=setdialog("+user.getValueAsString("id")+"); id=\"onlineUsersList_"+user.getValueAsString("id")+"\" hf=\"s?opr=chatRoomService&ac=gotoNewsInformationByIndex&selectUserid="+user.getValueAsString("id")+"\" style=\"height: 16px;line-height: 16px;\" target=\"dialog\" width=\"950\" height=\"500\" resizable=\"false\" maxable=\"false\" minable=\"false\"><span class=\"onlinepeople\" style=\"display:block;height:24px;line-height:24px;\" >"+user.getValueAsString("name")+"</span><input id=\"onlineusernum\" style=\"display:none\" value=\""+sessionUserCount+"\"></a>";}script.appendCall("addOnlineUser",onlineusers);for (ScriptSession scriptSession : sessions) {//发送消息scriptSession.addScript(script);}}});return "ok";
}

9、页面显示在线人员

脚本直接接收后台返回的在线人员,显示在index.jps

//获取当前在线人列表
function addOnlineUser(user){$("#onlineusers").html(user);
}

10、发送消息

页面调用:

<div id="valcontent" class="contentBox" layoutH="13"><div class="pageFormContent"><div class="tabs" id="<%=tabId %>" currentIndex="0" eventType="click"><div id="receivercontent" class="tabsContent" style="border-style:none;"><fieldset><dl><input type="text" readonly="readonly" id="receiverName" name="receiverName" size="20"/></dl></fieldset></div></div></div><div class="topside"><div class="chatcontent"><div id="chatcontent" class="eachcontent"></div></div></div><form id="mainForm" name="mainForm">  <input type="hidden" name="rel" value="lookupAddOnlydialog"/><input type="hidden" id="userid" value="<%= user.getId()%>"><input type="hidden" id="username" value="<%= user.getName()%>"><input type="hidden" id="receiverId"><div class="bottomside" ><div class="content"><textarea id="msgText" class="msgText"></textarea>  </div><input type="button" class="send" οnclick="javascript:singlePushMsg();" value="发言"><input type="button" class="clear" οnclick="javascript:reset0();" value="清空"><input type="button" id="searchmore" class="searchmore" οnclick="javascript:searchMoreChatLog();" value="查看更多消息"></div></form>
</div>

脚本处理:

<script type="text/javascript">//单对单聊天function singlePushMsg(){var userid = $("#userid").val(); var senderName = $("#username").val(); var receiverid = $("#receiverId").val();var receiverName = $("#receiverName").val();var msgText = $("#msgText").val();if (msgText == "" || msgText.length <= 0) {     alert("请输入内容");  return;  }chatRoomService.singlePushMsg(userid,senderName,receiverName,msgText,receiverid);}
</script>


后台service处理发送消息,且接收方和发送发实时接收消息

@SuppressWarnings("unchecked")  
public void singlePushMsg(final String senderId,final String senderName, final String receiverName, final String msgText,final String receiverId) {//发送消息(在线则发送,不在线则跳过)Browser.withAllSessionsFiltered(new ScriptSessionFilter() {@Overridepublic boolean match(ScriptSession session) {String sessionUserId = null;if(session != null){sessionUserId = (String) session.getAttribute("userId");}if(senderId.equals(sessionUserId) || receiverId.equals(sessionUserId)){return true;}return false;}}, new Runnable() {private ScriptBuffer script = new ScriptBuffer();@Overridepublic void run() {script.appendCall("doReply",senderName,receiverName,msgText);boolean receiverIdOnline = false;Collection<ScriptSession> sessions =  Browser.getTargetSessions();String sessionUserId =null;for (ScriptSession scriptSession : sessions) {//发送消息scriptSession.addScript(script);sessionUserId = (String) scriptSession.getAttribute("userId");String sql="";String chatlogsql="";SEntity chatlog=new SEntity("OA_SINGLE_CHAT_LOG");//判断接收者是否在线//存储聊天记录(接收者在线则存储聊天记录当前信息标记为已读,接收者不在线则存储聊天记录当前信息标记为未读if(receiverId.equals(sessionUserId)){receiverIdOnline = true;//处理发送的消息存入数据库					if(receiverId!=null && !receiverId.equals("")){//接收人id不为空,将接收方设置成离线sql="select * from OA_USER_ONLINE where USER_ID ="+receiverId;SEntityList user_onlinelist = baseDao.search(sql, null);SEntity user_online = null;if(user_onlinelist.size()>0){user_online=user_onlinelist.get(0);if(user_online!=null){user_online.setValue("STATUS", 1);user_online.setTableName("OA_USER_ONLINE");baseDao.update(user_online);}else{sql = "insert into OA_USER_ONLINE(USER_ID,STATUS) values ("+receiverId+",1)";baseDao.save(sql, null);}}else{sql = "insert into OA_USER_ONLINE(USER_ID,STATUS) values ("+receiverId+",1)";baseDao.save(sql, null);							}}chatlog.setValue("SEND_ID", senderId);chatlog.setValue("SEND_NAME", senderName);chatlog.setValue("RECEIVER_ID", receiverId);chatlog.setValue("RECEIVER_NAME", receiverName);chatlog.setValue("SEND_TIME", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));chatlog.setValue("SEND_CONTENT", msgText);chatlog.setValue("STATUS", 1);baseDao.save(chatlog);}else{//反之设置为在线if(receiverId!=null && !receiverId.equals("")){sql="select * from OA_USER_ONLINE where USER_ID ="+receiverId;SEntityList user_onlinelist = baseDao.search(sql, null);SEntity user_online = null;if(user_onlinelist.size()>0){user_online=user_onlinelist.get(0);if(user_online==null){sql = "insert into OA_USER_ONLINE(USER_ID,STATUS) values ("+receiverId+",2)";baseDao.save(sql, null);}else{user_online.setValue("STATUS", 2);user_online.setTableName("OA_USER_ONLINE");baseDao.update(user_online);}}}chatlog.setValue("SEND_ID", senderId);chatlog.setValue("SEND_NAME", senderName);chatlog.setValue("RECEIVER_ID", receiverId);chatlog.setValue("RECEIVER_NAME", receiverName);chatlog.setValue("SEND_TIME", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));chatlog.setValue("SEND_CONTENT", msgText);chatlog.setValue("STATUS", 2);baseDao.save(chatlog);}}}});
}

页面脚本实时接收 后台推送的聊天

function doReply(senderName,receiverName,msgText){if(receiverName == null || receiverName == ""){if($("#chatcontent").length == 0){chatRoomService.deleteScriptSessionFromChatRoom($("#username").val(),function(msg){});}else{$("#chatcontent").append("<span class=\"eachcontent\"><span class=\"chatpeo\">"+senderName+"</span>: "+msgText+"</span>");}}else{$("#chatcontent").append("<span class=\"eachcontent\"><span class=\"chatpeo\">"+senderName+"</span>:"+msgText+"</span>");}$("#msgText").val("");$(".chatcontent").scrollTop($(".chatcontent")[0].scrollHeight);
}


退出系统即该人员离线

<body scroll="no" οnunlοad="logoOut()"><input type="hidden" id="userid" value="<%= user.getId()%>">
</boby>

function logoOut() {var userid = $("#userid").val(); chatRoomService.deleteScriptSession(userid,function(msg){});
};

后台处理

public void deleteScriptSession(String userid, HttpServletRequest req) {  //此方法定义为下线注消,并更新所有人的在线人员列表Browser.withAllSessions(new Runnable() {private ScriptBuffer script = new ScriptBuffer();@Overridepublic void run() {Collection<ScriptSession> sessions =  Browser.getTargetSessions();Set<String> sessionUserIds = new HashSet<String>();//循环所有在线者,因一个人会有多个ScriptSession,去重String userIdStr="";for (ScriptSession scriptSession : sessions) {String sessionUserId = (String) scriptSession.getAttribute("userId");if(!sessionUserIds.contains(sessionUserId)){sessionUserIds.add(sessionUserId);userIdStr += sessionUserId + ",";}}if(userIdStr.endsWith(",")){userIdStr = userIdStr.substring(0, userIdStr.length()-1);}String sql="select id,name from sys_user where id in ("+userIdStr+") order by sortcol asc";SEntityList userlist = baseDao.search(sql, null);String onlineusers = "";for (SEntity user : userlist) {onlineusers += "<a οnclick=setdialog("+user.getValueAsString("id")+"); id=\"onlineUsersList_"+user.getValueAsString("id")+"\" hf=\"s?md=oa070201&ac=gotoNewsInformationByIndex&selectUserid="+user.getValueAsString("id")+"\" style=\"height: 16px;line-height: 16px;\" target=\"dialog\" width=\"950\" height=\"500\" resizable=\"false\" maxable=\"false\" minable=\"false\"><span class=\"onlinepeople\" style=\"display:block;height:24px;line-height:24px;\" >"+user.getValueAsString("name")+"</span></a>";}script.appendCall("addOnlineUser",onlineusers);for (ScriptSession scriptSession : sessions) {//发送消息scriptSession.addScript(script);}}});
}

页面展示



这篇关于dwr实现web单聊的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/960640

相关文章

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

OpenCV图像形态学的实现

《OpenCV图像形态学的实现》本文主要介绍了OpenCV图像形态学的实现,包括腐蚀、膨胀、开运算、闭运算、梯度运算、顶帽运算和黑帽运算,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起... 目录一、图像形态学简介二、腐蚀(Erosion)1. 原理2. OpenCV 实现三、膨胀China编程(

通过Spring层面进行事务回滚的实现

《通过Spring层面进行事务回滚的实现》本文主要介绍了通过Spring层面进行事务回滚的实现,包括声明式事务和编程式事务,具有一定的参考价值,感兴趣的可以了解一下... 目录声明式事务回滚:1. 基础注解配置2. 指定回滚异常类型3. ​不回滚特殊场景编程式事务回滚:1. ​使用 TransactionT

Android实现打开本地pdf文件的两种方式

《Android实现打开本地pdf文件的两种方式》在现代应用中,PDF格式因其跨平台、稳定性好、展示内容一致等特点,在Android平台上,如何高效地打开本地PDF文件,不仅关系到用户体验,也直接影响... 目录一、项目概述二、相关知识2.1 PDF文件基本概述2.2 android 文件访问与存储权限2.

使用Python实现全能手机虚拟键盘的示例代码

《使用Python实现全能手机虚拟键盘的示例代码》在数字化办公时代,你是否遇到过这样的场景:会议室投影电脑突然键盘失灵、躺在沙发上想远程控制书房电脑、或者需要给长辈远程协助操作?今天我要分享的Pyth... 目录一、项目概述:不止于键盘的远程控制方案1.1 创新价值1.2 技术栈全景二、需求实现步骤一、需求

Spring Shell 命令行实现交互式Shell应用开发

《SpringShell命令行实现交互式Shell应用开发》本文主要介绍了SpringShell命令行实现交互式Shell应用开发,能够帮助开发者快速构建功能丰富的命令行应用程序,具有一定的参考价... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定义S

SpringBatch数据写入实现

《SpringBatch数据写入实现》SpringBatch通过ItemWriter接口及其丰富的实现,提供了强大的数据写入能力,本文主要介绍了SpringBatch数据写入实现,具有一定的参考价值,... 目录python引言一、ItemWriter核心概念二、数据库写入实现三、文件写入实现四、多目标写入

Android Studio 配置国内镜像源的实现步骤

《AndroidStudio配置国内镜像源的实现步骤》本文主要介绍了AndroidStudio配置国内镜像源的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、修改 hosts,解决 SDK 下载失败的问题二、修改 gradle 地址,解决 gradle

SpringSecurity JWT基于令牌的无状态认证实现

《SpringSecurityJWT基于令牌的无状态认证实现》SpringSecurity中实现基于JWT的无状态认证是一种常见的做法,本文就来介绍一下SpringSecurityJWT基于令牌的无... 目录引言一、JWT基本原理与结构二、Spring Security JWT依赖配置三、JWT令牌生成与

SpringBoot实现微信小程序支付功能

《SpringBoot实现微信小程序支付功能》小程序支付功能已成为众多应用的核心需求之一,本文主要介绍了SpringBoot实现微信小程序支付功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作... 目录一、引言二、准备工作(一)微信支付商户平台配置(二)Spring Boot项目搭建(三)配置文件