在进行聊天之前呢,我们在前文的基础上还要再增加一个查询聊天记录的action,这里我们直接在UserAction这个类中自定义loadRecord方法,如下:
其中getChatRecords方法已经在UserService类中实现了并且是按照时间,用户排序的。接受sid,rid参数,发送者以及接受者。这些参数在上一篇文章中已经有过定义了,所以这里我们直接使用。

 /*** 获取聊天记录* @return 返回json*/public String loadRecords(){Map<Integer,Object> result = userService.getChatRecords(sid,rid);data.put("code",200);data.put("info","获取聊天记录成功");data.put("data",result);return SUCCESS;}

修改P2PChatRoom程序

  • 在onOpen方法中获取登录信息,向所有在线用户广播当前用户上线
  • 根据ws连接参数判断用户是否请求与其他在线用户连接
  • 如何发送在线列表(在前面的文章中已经解决了)
  • 用户聊天匹配以及下线广播
    完整程序如下(完备版):
package cn.zipple.ws;import cn.zipple.dao.impl.UserDaoImpl;
import cn.zipple.encoder.ServerEncoder;
import cn.zipple.entity.ChatRecord;
import cn.zipple.entity.User;
import cn.zipple.service.UserService;
import cn.zipple.util.Log;import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
/*** Created by zipple on 2017/11/14.* 点对点聊天室*/
@ServerEndpoint(value ="/chatRoom/{username}",configurator=HttpSessionWSHelper.class,encoders = {ServerEncoder.class})
//@ServerEndpoint(value ="/chatRoom",configurator=HttpSessionWSHelper.class)
public class P2PChatRoom {private Session session;//本身的ws sessionprivate HttpSession httpSession;//对应的 httpSessionprivate static CopyOnWriteArraySet<P2PChatRoom> P2PChatRoomSet = new CopyOnWriteArraySet<>();//保证线程安全private Session targetSession;//目标sessionprivate String targetName;//目标nameprivate UserDaoImpl userDao;public P2PChatRoom(){Log.info("---------------启动webSocket P2PChatRoom聊天室-----------------------");userDao =new UserService().getUserDao();}
//初次连接初始化操作private void init(Session session, EndpointConfig config){this.setSession(session);HttpSession httpSession= (HttpSession) config.getUserProperties().get(HttpSession.class.getName());this.setHttpSession(httpSession);}//与用户配对private void connect2Users(String username,User self){boolean flag =false;for (P2PChatRoom p2pChatRoom: P2PChatRoomSet){User user = (User) p2pChatRoom.getHttpSession().getAttribute("user");if (user.getName().equals(username)){targetName=username;//必须要在能连接会话的时候赋值targetSession=p2pChatRoom.getSession();//获取目标对象的Session//同时给对方也连接本身的targetp2pChatRoom.setTargetSession(session);p2pChatRoom.setTargetName(self.getName());flag=true;break;}}if (flag){ChatRecord sysSelf= new ChatRecord(new User("系统","000",0),self.getId(),"*连接"+targetName+"成功");ChatRecord sysTarget= new ChatRecord(new User("系统","000",0),self.getId(),self.getName()+"请求与您通话!");//不等待对方同意try {session.getBasicRemote().sendObject(sysSelf);targetSession.getBasicRemote().sendObject(sysTarget);} catch (Exception e) {e.printStackTrace();}Log.info("会话连接成功");}else{ChatRecord sysSelf= new ChatRecord(new User("系统","000",0),self.getId(),"连接失败.对方不在线");try {session.getBasicRemote().sendObject(sysSelf);} catch (Exception e) {e.printStackTrace();}Log.info("会话连接失败");}}/*** 将消息发送给所有人* @param msg 消息*/public void send2All(String msg) throws IOException, EncodeException {ChatRecord chatRecord= new ChatRecord(new User("系统","000",0),0,msg);//发送在线列表for (P2PChatRoom p2pChatRoom: P2PChatRoomSet){p2pChatRoom.getSession().getBasicRemote().sendObject(chatRecord);}}/*** 发送在线列表* @throws IOException IO异常* @throws EncodeException 编码器异常*/private void sendOnlineUsers() throws IOException, EncodeException {//当有新用户连接服务器时,将在线列表发送给所有在线用户Log.info("发送在线列表");Set<User> userSet =new HashSet<>();for (P2PChatRoom p2pChatRoom: P2PChatRoomSet){User temp = (User) p2pChatRoom.getHttpSession().getAttribute("user");if (temp!=null){temp.setChatRecords(null);//不需要加载聊天记录----否则会引起死循环解析userSet.add(temp);}}//发送在线列表for (P2PChatRoom p2pChatRoom: P2PChatRoomSet){p2pChatRoom.getSession().getBasicRemote().sendObject(userSet);}}@OnOpenpublic void onOpen(@PathParam("username")String username, Session session, EndpointConfig config){try {Log.info("正在连接服务器.....,username:"+username);init(session,config);P2PChatRoomSet.add(this);Log.info("服务器当前连接数:"+P2PChatRoomSet.size());User self = (User)httpSession.getAttribute("user");Log.info("ws自己对应的httpSession:"+self.getName());send2All(self.getName()+"上线");if (username!=null&&!username.equals("null")){connect2Users(username,self);sendOnlineUsers();}else{Log.info("*连接服务器成功");//发送在线列表sendOnlineUsers();}}catch (Exception e){e.printStackTrace();}}@OnMessagepublic void onMessage(Session session, String msg){User self = (User)httpSession.getAttribute("user");if (targetName==null||targetSession==null){//未选择私聊的连接者Log.info("未选择私聊的连接者:"+self.getName()+" 消息将转发给自己");ChatRecord me = new ChatRecord(self,self.getId(),msg);try {session.getBasicRemote().sendObject(me);} catch (Exception e) {e.printStackTrace();}}else{Log.info("服务器收到来自"+self.getName()+"转发给"+targetName+"的信息:"+msg);User target = userDao.getUserByUsername(targetName);ChatRecord chats = new ChatRecord(self,target.getId(),msg);userDao.save(chats);//保存聊天记录----是不是应该发送出去后再保存try {if (targetSession.isOpen()){targetSession.getBasicRemote().sendObject(chats);}else{session.getBasicRemote().sendObject(new ChatRecord(new User("系统","000",0),0,"对方已下线"));}// session.getBasicRemote().sendObject(chats);不用发送给自己}catch (Exception e){e.printStackTrace();}}}@OnErrorpublic void onError(Session session, Throwable throwable){User user = (User)httpSession.getAttribute("user");if (user!=null){Log.info("用户:"+user.getName()+" 连接异常. throwable:"+throwable.getMessage());}else{Log.info("session:"+session.getId()+"连接异常. throwable:"+throwable.getMessage());}}@OnClosepublic void onClose(Session session, CloseReason reason){try {User user = (User)httpSession.getAttribute("user");P2PChatRoomSet.remove(this);//会不会remove 两次if (user!=null){Log.info(user.getName()+"断开连接,原因:"+reason.getReasonPhrase());//下线提醒send2All(user.getName()+"下线");//释放连接}else{Log.info("session:"+session.getId()+"断开连接,原因:"+reason.getReasonPhrase());}//发送在线列表sendOnlineUsers();}catch (Exception e){e.printStackTrace();}}public Session getSession() {return session;}public void setSession(Session session) {this.session = session;}public HttpSession getHttpSession() {return httpSession;}public void setHttpSession(HttpSession httpSession) {this.httpSession = httpSession;}public Session getTargetSession() {return targetSession;}public void setTargetSession(Session targetSession) {this.targetSession = targetSession;}public String getTargetName() {return targetName;}public void setTargetName(String targetName) {this.targetName = targetName;}public static CopyOnWriteArraySet<P2PChatRoom> getP2PChatRoomSet() {return P2PChatRoomSet;}public static void setP2PChatRoomSet(CopyOnWriteArraySet<P2PChatRoom> p2PChatRoomSet) {P2PChatRoomSet = p2PChatRoomSet;}public UserDaoImpl getUserDao() {return userDao;}public void setUserDao(UserDaoImpl userDao) {this.userDao = userDao;}
}

基于Struts2和hibernate的WebSocket聊天室的实现教程五:聊天机制相关推荐

  1. 基于阿里云用C/C++做了一个http协议与TCP协议的web聊天室的服务器——《干饭聊天室》

    基于阿里云用C/C++做了一个http协议与TCP协议的web聊天室的服务器--<干饭聊天室> 在这里首先感谢前端小伙伴飞鸟 前端技术请看一款基于React.C++,使用TCP/HTTP协 ...

  2. Java websocket + redis 实现多人单聊天室,多人多聊天室, 一对一聊天

    多人,单聊天室版 FEATURE 多人聊天, 界面简洁美观, 使用ueditor支持发送文字,图片信息 群聊成员列表, 登入登出公告 存储聊天记录, 查看历史消息 技术点 使用CopyOnWriteM ...

  3. SpringBoot与webSocket实现在线聊天室——实现私聊+群聊+聊天记录保存

    SpringBoot与webSocket实现在线聊天室--实现私聊+群聊+聊天记录保存 引用参考:原文章地址:https://blog.csdn.net/qq_41463655/article/det ...

  4. php聊天室系统实验报告,PHP聊天室技术

    1.前言 上网聊天是时下最流行的交友方式.各大网站推出的聊天室都各具特色. 聊天室主要分为WebChat.BBSChat 两种.BBSChat是基于Telnet的Tcp协议,是BBS的附设功能,需要客 ...

  5. LayIM 3.9.1与ASP.NET SignalR实现Web聊天室快速入门(五)之使用RabbitMQ缓存消息

    前言 本系列文章特点:使用ASP.NET SignalR和LayIM快速入门对接,实现一对一聊天,群聊,添加聊天群组,查找聊天记录等功能.源代码不包含LayIM的源代码,因为官方并没开源属于收费资源, ...

  6. 开视频聊天室怎么赚钱 如何利用聊天室赚钱

    本专题主要介绍下 开视频聊天室怎么赚钱, 如何利用聊天室赚钱,视频聊天室是一种新型的网络娱乐消费行业,几乎所有上网者都有过在聊天室里和天南 海北的男男女女胡吹海侃的经历.也有许多网民热衷此道,把在线聊 ...

  7. python聊天室源代码_Python实现文字聊天室

    你是否想过用所学的Python开发一个图形界面的聊天室程序啊? 像这样的: 如果你想开发这样一个有点怀旧风格的聊天程序,那么可以接着看: 要开发这个聊天程序,你需要具备以下知识点: asyncore ...

  8. java聊天室 博客_java网络聊天室

    功能简述: 1.可以多用户登陆聊天室,用户可以选择私聊或者对所有人聊天.(这里时间关系仅实现群聊,私聊只要将私聊消息和群聊消息封装开来即可实现) 2.有人登陆聊天室时由系统通知所有在线用户,并刷新在线 ...

  9. asp.net ajax聊天室,ASP.NET MVC4异步聊天室的示例代码

    本文介绍了ASP.NET MVC4异步聊天室的示例代码,分享给大家,具体如下: 类图: Domain层 IChatRoom.cs using System; using System.Collecti ...

  10. wpf 语音通话_WPF+WCF一步一步打造音频聊天室(三):语音聊天

    前一篇文章中实现了文字聊天和共享白板的功能,这篇文章中,我将在前一篇文章的基础上实现语音聊天的功能.语音聊天要比文字聊天和共享白板难度要大一点. 实现的大概的流程为: 1.一个聊天室成员向另外一个成员 ...

最新文章

  1. WindowsForm 计算器
  2. python2 与 python3 语法区别--转
  3. java 得到checkbox_【JavaWeb】获得选中的checkbox的value
  4. android主动显示流程,Activity加载显示基本流程
  5. Oracle笔记:创建表空间、创建用户、授权
  6. python从大到小排序_python作业:用嵌套的列表存储学生成绩数据,并编程完成如下操作...
  7. java search 不能使用方法_ElasticSearch实战系列三: ElasticSearch的JAVA API使用教程
  8. 【Java从0到架构师】项目实战 - 前后端分离、后端校验、Swagger、全局异常处理
  9. 计算机页面的工具,魔兽窗口化工具
  10. c语言题库及答案(选择题,C语言题库及答案(选择题).doc
  11. faststone capture截图,怎么截不出图?关于FastStone Capture无法截图、FastStone Capture捕捉矩形区域之后没反应、
  12. 【人因工程】认知行为可靠性评价浅谈
  13. 流量直升机-千牛插件功能列表
  14. 6-1 数据结构实验之排序八:快速排序 (20 分)
  15. Softmax回归函数
  16. linux编辑conf,Linux:我如何编辑resolv.conf
  17. iOS 在 Xcode 中重命名项目名称
  18. 也许履历表可以这样填
  19. HTML5篇学习笔记
  20. 几张表格怎么联动_如何实现多张excel表格数据联动-Excel 如何实现多级下拉菜单的联动...

热门文章

  1. 手机服务器连接视频文件夹吗,巧用手机自带功能向电脑传输视频 华为小米苹果均适用...
  2. go语言 flag用法
  3. 讯飞2021年营收183亿:同比增41% 净利为15.56亿
  4. 2022年中职网络空间安全国赛竞赛题解析仅代表自己的建议——2022年中职网络安全国赛竞赛试题1解析
  5. SPSS提示“列表中不允许存在字符串变量”的解决方法
  6. [状压dp][BZOJ3717][PA2014]Pakowanie
  7. 开启微信公众号定位服务器,微信公众号定位学会这几步就够了!
  8. 数字鉴相,关于相位差的提取
  9. VirtualBox中出现“0x00000000指令引用的0x00000000内存该内存不能为written 和visual studio Just in time debugger error
  10. 如何截图一张完整的表_wps2016表格太长怎么截图打印?