dwr实现web单聊

来源:互联网 发布:北京淘宝城 编辑:程序博客网 时间:2024/06/05 06:21

通过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 onclick=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" onclick="javascript:singlePushMsg();" value="发言"><input type="button" class="clear" onclick="javascript:reset0();" value="清空"><input type="button" id="searchmore" class="searchmore" onclick="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" onunload="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 onclick=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);}}});}

页面展示



1 0
原创粉丝点击