其他分享
首页 > 其他分享> > 使用SpringBoot + WebSocket实现单人聊天

使用SpringBoot + WebSocket实现单人聊天

作者:互联网

## 前言 >最近在做一个聊天功能,具体需求:类似微信,在一个好友列表中,点击某个好友就可以建立与该好友的聊天连接,向该好友发送消息,对方能够实时显示出来,进行真正意义上的聊天。 在做之前,不管在界面布局,还是功能实现方面都下了一点功夫,最终还是一点点实现了,现在就记录一下。 在编码之前得先了解一下`WebSocket` > 1. 什么是`WebSocket`? > > * `WebSocket`,即Web浏览器与Web服务器之间全双工通信标准;是HTML5中的协议,支持持久连续,http协议不支持持久性连接。Http1.0和HTTP1.1都不支持持久性的链接,HTTP1.1中的keep-alive,将多个http请求合并为1个 > * 一旦确立`WebSocket`通信连接,不论服务器还是客户端,任意一方都可直接向对方发送报文 > > 2. `WebSocket`特点? > > * 推送功能:支持由服务器向客户端推送数据的推送功能,这样,服务器可直接发送数据,而不必等待客户端的请求 > * 减少通信量:只要建立起`WebSocket`,就可以一直保持连接状态 > > > 头部字段多了下面2个属性: > > ```http > Upgrade:webSocket > Connection:Upgrade > ``` ![](https://www.icode9.com/i/ll/?i=img_convert/6cbfa5cb7d9b8ff57af3a42254f6f2ca.png) ## 1、实现效果 ![](https://www.icode9.com/i/ll/?i=img_convert/c208de0df2d7bf27f7a958bafe437e19.png) 点击左侧好友列表时,会建立websocket连接,把当前发消息的用户发送给websocket服务器 ![](https://www.icode9.com/i/ll/?i=img_convert/6d52813766d6e2473d860ee76c8c9fc4.png) 输入消息 ![](https://www.icode9.com/i/ll/?i=img_convert/77b7e01e51d28f605f60df299a6a0b05.png) ![](https://www.icode9.com/i/ll/?i=img_convert/2a6bb7c99100d7e501a8b5448f8ca702.png) ![](https://www.icode9.com/i/ll/?i=img_convert/b4ac4768b14b6df1ffb7f6e88aec762d.png) ## 2、前端实现 ```js ``` ```js ``` ```vue ``` ## 3、后端实现 添加依赖 ```java org.springframework.boot spring-boot-starter-websocket ``` ```java // WebSocketController.java @Controller @ServerEndpoint(value = "/websocket/{user}") @Api(tags = "业务模块-websocket连接接口") public class WebSocketController { // 这里使用静态,让 service 属于类 private static ChatMsgService chatMsgService; // 注入的时候,给类的 service 注入 @Resource public void setChatService(ChatMsgService chatService) { WebSocketController.chatMsgService = chatService; } // 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 private static int onlineCount = 0; // concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识 private static ConcurrentHashMap<String, WebSocketController> webSocketSet = new ConcurrentHashMap<String, WebSocketController>(); // 与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session WebSocketSession; // 记录当前发消息的用户 private String user = ""; /** * 连接建立成功调用的方法 * * session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据 */ @OnOpen public void onOpen(@PathParam(value = "user") String param, Session WebSocketsession) { user = param; // System.out.println(user); this.WebSocketSession = WebSocketsession; webSocketSet.put(param, this);// 加入map中 addOnlineCount(); // 在线数加1 // System.out.println("有新连接加入!当前在线人数为" + getOnlineCount()); } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { if (!user.equals("")) { webSocketSet.remove(user); // 从set中删除 subOnlineCount(); // 在线数减1 // System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount()); } } /** * 收到客户端消息后调用的方法 * * @param chatmsg 客户端发送过来的消息 * @param session 可选的参数 */ @OnMessage public void onMessage(String chatmsg, Session session) throws SystemException{ JSONObject jsonObject = JSONObject.parseObject(chatmsg); //给指定的人发消息 sendToUser(jsonObject.toJavaObject(ChatMsgVO.class)); //sendAll(message); } /** * 给指定的人发送消息 * * @param chatMsg 消息对象 */ public void sendToUser(ChatMsgVO chatMsg) throws SystemException{ String fromUser = chatMsg.getMFromUser(); String mMsg = chatMsg.getMMsg(); System.out.println(fromUser); mMsg= EmojiFilter.filterEmoji(mMsg);//过滤输入法输入的表情 chatMsgService.InsertChatMsg(chatMsg); try { if (webSocketSet.get(fromUser) != null) { webSocketSet.get(fromUser).sendMessage(chatMsg.getMFromUser()+"|"+mMsg); }else{ webSocketSet.get(chatMsg.getMFromUser()).sendMessage("0"+"|"+"当前用户不在线"); } } catch (IOException e) { throw new SystemException(SystemCodeEnum.PARAMETER_ERROR,e.getMessage()); } } /** * 给所有人发消息 * * @param message */ private void sendAll(String message) { String sendMessage = message.split("[|]")[1]; //遍历HashMap for (String key : webSocketSet.keySet()) { try { //判断接收用户是否是当前发消息的用户 if (!user.equals(key)) { webSocketSet.get(key).sendMessage(sendMessage); System.out.println("key = " + key); } } catch (IOException e) { e.printStackTrace(); } } } /** * 发生错误时调用 * * @param session * @param error */ @OnError public void one rror(Session session, Throwable error) { error.printStackTrace(); } /** * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。 * * @param message * @throws IOException */ public void sendMessage(String message) throws IOException { this.WebSocketSession.getBasicRemote().sendText(message); //this.session.getAsyncRemote().sendText(message); } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocketController.onlineCount++; } public static synchronized void subOnlineCount() { WebSocketController.onlineCount--; } } ``` ```java //ChatController.java @RestController @RequestMapping("business/chat") public class ChatMsgController { @Resource private ApiUserService apiUserService; @Resource private ChatMsgService chatMsgService; @Resource private ChatFriendsService chatFriendsService; @ApiOperation(value = "获取好友聊天记录", notes = "根据当前用户查询好友聊天记录") @GetMapping("/getFriendMsg/{username}") public ResponseBean<List> getFriendMsg(@PathVariable String username) throws SystemException { UserInfoVO userInfoVO = apiUserService.info(); List chatMsgs = chatMsgService.getFriendMsg(userInfoVO.getUsername(), username); return ResponseBean.success(chatMsgs); } @ApiOperation(value = "获取用户好友", notes = "根据用户id查询用户好友") @GetMapping("/getfriends/{id}") public ResponseBean<List> getFriends(@PathVariable Long id) throws SystemException { List chatFriendsList = chatFriendsService.getFriends(id); return ResponseBean.success(chatFriendsList); } } ```

标签:WebSocket,SpringBoot,img,单人,void,param,String,public,客户端
来源: https://blog.51cto.com/u_15192324/2900483