基于Struts2和hibernate的WebSocket聊天室的实现教程五:聊天机制
来源:互联网 发布:gta5 抗锯齿优化 编辑:程序博客网 时间:2024/06/05 17:41
在进行聊天之前呢,我们在前文的基础上还要再增加一个查询聊天记录的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 session private HttpSession httpSession;//对应的 httpSession private static CopyOnWriteArraySet<P2PChatRoom> P2PChatRoomSet = new CopyOnWriteArraySet<>();//保证线程安全 private Session targetSession;//目标session private String targetName;//目标name private 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 //同时给对方也连接本身的target p2pChatRoom.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); } } @OnOpen public 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(); } } @OnMessage public 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(); } } } @OnError public 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()); } } @OnClose public 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; }}
阅读全文
1 0
- 基于Struts2和hibernate的WebSocket聊天室的实现教程五:聊天机制
- 基于Struts2和hibernate的WebSocket聊天室的实现教程三:Hibernate个人信息管理
- 基于Struts2和hibernate的WebSocket聊天室的实现教程四:实现登录接口
- 基于Struts2和hibernate的WebSocket聊天室的实现教程一:环境搭建
- 基于Struts2和hibernate的WebSocket聊天室的实现教程二:发送在线列表
- 基于Struts2和hibernate的WebSocket聊天室的实现教程六:界面原型及通信请求
- SSM(五)基于webSocket的聊天室
- SSM(五)基于webSocket的聊天室
- SSM(五)基于webSocket的聊天室
- 基于websocket的简易聊天室的实现
- iOS基于WebSocket的聊天机制
- php基于websocket实现的在线聊天室
- 基于 SpringBoot 和 webSocket 的匿名聊天室
- 基于websocket和swoole的简易聊天室
- java WebSocket实现简单的聊天室(包括群发和点对点聊天)
- WebSocket聊天室的实现
- 基于websocket+java聊天系统的实现
- 基于WebSocket的简易聊天室
- 文件编码
- [python入门进阶]一个糊弄人的文档加密解码器
- monkeyrunner环境搭建
- Ijkplayer使用
- java实现Excel导入导出
- 基于Struts2和hibernate的WebSocket聊天室的实现教程五:聊天机制
- CentOS 或 RedHat 的 root密码重置
- c++ 第六章第二题
- 蓝桥杯题解-取球博弈1
- Caused by: java.lang.NoClassDefFoundError: Lorg/apache/logging/log4j/Logger
- MySQL学习之四:数据库及表的修改和删除
- 相机定标
- Maximum sum 二维最大子段和
- [2017.11.19]异常&File类&IO流