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

相关文章

java中BigDecimal里面的subtract函数介绍及实现方法

《java中BigDecimal里面的subtract函数介绍及实现方法》在Java中实现减法操作需要根据数据类型选择不同方法,主要分为数值型减法和字符串减法两种场景,本文给大家介绍java中BigD... 目录Java中BigDecimal里面的subtract函数的意思?一、数值型减法(高精度计算)1.

C#代码实现解析WTGPS和BD数据

《C#代码实现解析WTGPS和BD数据》在现代的导航与定位应用中,准确解析GPS和北斗(BD)等卫星定位数据至关重要,本文将使用C#语言实现解析WTGPS和BD数据,需要的可以了解下... 目录一、代码结构概览1. 核心解析方法2. 位置信息解析3. 经纬度转换方法4. 日期和时间戳解析5. 辅助方法二、L

使用Python和Matplotlib实现可视化字体轮廓(从路径数据到矢量图形)

《使用Python和Matplotlib实现可视化字体轮廓(从路径数据到矢量图形)》字体设计和矢量图形处理是编程中一个有趣且实用的领域,通过Python的matplotlib库,我们可以轻松将字体轮廓... 目录背景知识字体轮廓的表示实现步骤1. 安装依赖库2. 准备数据3. 解析路径指令4. 绘制图形关键

C/C++中OpenCV 矩阵运算的实现

《C/C++中OpenCV矩阵运算的实现》本文主要介绍了C/C++中OpenCV矩阵运算的实现,包括基本算术运算(标量与矩阵)、矩阵乘法、转置、逆矩阵、行列式、迹、范数等操作,感兴趣的可以了解一下... 目录矩阵的创建与初始化创建矩阵访问矩阵元素基本的算术运算 ➕➖✖️➗矩阵与标量运算矩阵与矩阵运算 (逐元

C/C++的OpenCV 进行图像梯度提取的几种实现

《C/C++的OpenCV进行图像梯度提取的几种实现》本文主要介绍了C/C++的OpenCV进行图像梯度提取的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录预www.chinasem.cn备知识1. 图像加载与预处理2. Sobel 算子计算 X 和 Y

C/C++和OpenCV实现调用摄像头

《C/C++和OpenCV实现调用摄像头》本文主要介绍了C/C++和OpenCV实现调用摄像头,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录准备工作1. 打开摄像头2. 读取视频帧3. 显示视频帧4. 释放资源5. 获取和设置摄像头属性

c/c++的opencv图像金字塔缩放实现

《c/c++的opencv图像金字塔缩放实现》本文主要介绍了c/c++的opencv图像金字塔缩放实现,通过对原始图像进行连续的下采样或上采样操作,生成一系列不同分辨率的图像,具有一定的参考价值,感兴... 目录图像金字塔简介图像下采样 (cv::pyrDown)图像上采样 (cv::pyrUp)C++ O

c/c++的opencv实现图片膨胀

《c/c++的opencv实现图片膨胀》图像膨胀是形态学操作,通过结构元素扩张亮区填充孔洞、连接断开部分、加粗物体,OpenCV的cv::dilate函数实现该操作,本文就来介绍一下opencv图片... 目录什么是图像膨胀?结构元素 (KerChina编程nel)OpenCV 中的 cv::dilate() 函

Python使用FFmpeg实现高效音频格式转换工具

《Python使用FFmpeg实现高效音频格式转换工具》在数字音频处理领域,音频格式转换是一项基础但至关重要的功能,本文主要为大家介绍了Python如何使用FFmpeg实现强大功能的图形化音频转换工具... 目录概述功能详解软件效果展示主界面布局转换过程截图完成提示开发步骤详解1. 环境准备2. 项目功能结

SpringBoot使用ffmpeg实现视频压缩

《SpringBoot使用ffmpeg实现视频压缩》FFmpeg是一个开源的跨平台多媒体处理工具集,用于录制,转换,编辑和流式传输音频和视频,本文将使用ffmpeg实现视频压缩功能,有需要的可以参考... 目录核心功能1.格式转换2.编解码3.音视频处理4.流媒体支持5.滤镜(Filter)安装配置linu