本文是vhr系列第15篇,项目地址:https://github.com/lenve/vhr 前端
在线聊天使用了SpringBoot+WebSocket实现,为了保证用户隐私,全部的聊天数据都保存在系统本地,服务器只进行了数据转发。OK,那接下来,咱们来看下大体的实现步骤。ios
服务端首先加入websocket依赖,以下:git
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
建立WebSocket的配置类,以下:github
@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) { stompEndpointRegistry.addEndpoint("/ws/endpointChat").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker("/queue","/topic"); } }
这里我并未使用原生的websocket协议,而是使用了websocket的子协议stomp,方便一些。消息代理既使用了/queue
,又使用了/topic
,主要是由于我这里既有点对点的单聊(queue),也有发送系统消息的群聊(topic)。 web
建立websocket处理类Controller,以下:spring
@Controller public class WsController { @Autowired SimpMessagingTemplate messagingTemplate; @MessageMapping("/ws/chat") public void handleChat(Principal principal, String msg) { String destUser = msg.substring(msg.lastIndexOf(";") + 1, msg.length()); String message = msg.substring(0, msg.lastIndexOf(";")); messagingTemplate.convertAndSendToUser(destUser, "/queue/chat", new ChatResp(message, principal.getName())); } }
消息协议很简单:发送来的消息,最后一个;
后面跟的是该条消息要发送到哪一个用户,这里经过字符串截取将之提取出来。响应消息包含两个字段,一个是消息内容,一个是该条消息由谁发送。 数据库
OK,如此以后,咱们的服务端就写好了,很简单。编程
前端代码稍微复杂,我这里主要和小伙伴介绍下个人大体思路和核心代码,具体代码小伙伴能够star源码进行研究。 json
首先,当用户登陆成功以后,我就发起websocket的链接,将ws链接起来,ws的代码我主要写在了store中,以下:axios
connect(context){ context.state.stomp = Stomp.over(new SockJS("/ws/endpointChat")); context.state.stomp.connect({}, frame=> { context.state.stomp.subscribe("/user/queue/chat", message=> { var msg = JSON.parse(message.body); var oldMsg = window.localStorage.getItem(context.state.user.username + "#" + msg.from); if (oldMsg == null) { oldMsg = []; oldMsg.push(msg); window.localStorage.setItem(context.state.user.username + "#" + msg.from, JSON.stringify(oldMsg)) } else { var oldMsgJson = JSON.parse(oldMsg); oldMsgJson.push(msg); window.localStorage.setItem(context.state.user.username + "#" + msg.from, JSON.stringify(oldMsgJson)) } if (msg.from != context.state.currentFriend.username) { context.commit("addValue2DotMap", "isDot#" + context.state.user.username + "#" + msg.from); } //更新msgList var oldMsg2 = window.localStorage.getItem(context.state.user.username + "#" + context.state.currentFriend.username); if (oldMsg2 == null) { context.commit('updateMsgList', []); } else { context.commit('updateMsgList', JSON.parse(oldMsg2)); } }); }, failedMsg=> { }); }
链接成功以后,就能够准备接收服务端的消息了,接收到服务端的消息后,数据保存在localStorage中,保存格式是 当前用户名#消息发送方用户名:[{from:'消息发送方',msg:'消息内容'}]
,注意后面的是一个json数组,整个存储的key之因此用当前用户名#消息发送方用户名
是为了不同一个浏览器多个用户登陆所产生的数据紊乱,OK,这样两我的的聊天记录都将保存在这个数组中。在聊天展现页面,当数组中的数据发生变化时,自动更新。
在聊天页面,经过stomp发送消息,以下:
this.$store.state.stomp.send("/ws/chat", {}, this.msg + ";" + this.currentFriend.username);
注意每条消息的内容除了内容自己外,还要加上当前发送者的名字。
每次发送成功后更新聊天页面便可。更新聊天页面代码以下:
<template v-for="msg in msgList"> <!--发送来的消息--> <div style="display: flex;justify-content: flex-start;align-items: center;box-sizing: border-box;" v-if="msg.from==currentFriend.username"> <img :src="currentFriend.userface" class="userfaceImg"> <div style="display: inline-flex;border-style: solid;border-width: 1px;border-color: #20a0ff;border-radius: 5px;padding: 5px 8px 5px 8px"> {{msg.msg}} </div> </div> <!--发出去的消息--> <div v-if="msg.from!=currentFriend.username" style="display: flex;justify-content: flex-end;align-items: center;box-sizing: border-box;"> <div style="display: inline-flex;border-style: solid;border-width: 1px;border-color: #20a0ff;border-radius: 5px;padding: 5px 8px 5px 8px;margin-right: 3px;background-color: #9eea6a"> {{msg.msg}} </div> <img :src="currentUser.userface" class="userfaceImg"> </div> </template>
若是消息中的from字段的值,就是当前聊天的用户名,则是发送来的消息,不然就是发出去的消息,不一样的消息设置不一样的样式便可。
核心代码基本如此,可是琐碎的细节实际上是比较多的,小伙伴能够star源码进行研究。
本系列其余文章:
1.SpringBoot+Vue先后端分离,使用SpringSecurity完美处理权限问题(一)
2.SpringBoot+Vue先后端分离,使用SpringSecurity完美处理权限问题(二)
3.SpringSecurity中密码加盐与SpringBoot中异常统一处理
4.axios请求封装和异常统一处理
5.权限管理模块中动态加载Vue组件
6.SpringBoot+Vue先后端分离,使用SpringSecurity完美处理权限问题(六)
7.vhr部门管理数据库设计与编程
8.使用MyBatis轻松实现递归查询与存储过程调用
9.ElementUI中tree控件踩坑记
10.SpringBoot中自定义参数绑定
11.SpringBoot中使用POI,快速实现Excel导入导出
12.SpringBoot中发送QQ邮件
13.SpringBoot中使用Freemarker构建邮件模板
14.SpringBoot+WebSocket实如今线聊天(一)
关注公众号,能够及时接收到最新文章: