一、前言

本文将基于 SpringBoot + Vue + WebSocket 实现一个简单的在线聊天功能

页面如下:

在线体验地址:http://www.zhengqingya.com:8101

二、SpringBoot + Vue + WebSocket 实现在线聊天

1、引入websocket依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2、websocket 配置类

@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

3、websocket 处理类Controller

@Slf4j
@Component
@ServerEndpoint("/groupChat/{sid}/{userId}")
public class WebSocketServerController { /**
* 房间号 -> 组成员信息
*/
private static ConcurrentHashMap<String, List<Session>> groupMemberInfoMap = new ConcurrentHashMap<>();
/**
* 房间号 -> 在线人数
*/
private static ConcurrentHashMap<String, Set<Integer>> onlineUserMap = new ConcurrentHashMap<>(); /**
* 收到消息调用的方法,群成员发送消息
*
* @param sid:房间号
* @param userId:用户id
* @param message:发送消息
*/
@OnMessage
public void onMessage(@PathParam("sid") String sid, @PathParam("userId") Integer userId, String message) {
List<Session> sessionList = groupMemberInfoMap.get(sid);
Set<Integer> onlineUserList = onlineUserMap.get(sid);
// 先一个群组内的成员发送消息
sessionList.forEach(item -> {
try {
// json字符串转对象
MsgVO msg = JSONObject.parseObject(message, MsgVO.class);
msg.setCount(onlineUserList.size());
// json对象转字符串
String text = JSONObject.toJSONString(msg);
item.getBasicRemote().sendText(text);
} catch (IOException e) {
e.printStackTrace();
}
});
} /**
* 建立连接调用的方法,群成员加入
*
* @param session
* @param sid
*/
@OnOpen
public void onOpen(Session session, @PathParam("sid") String sid, @PathParam("userId") Integer userId) {
List<Session> sessionList = groupMemberInfoMap.computeIfAbsent(sid, k -> new ArrayList<>());
Set<Integer> onlineUserList = onlineUserMap.computeIfAbsent(sid, k -> new HashSet<>());
onlineUserList.add(userId);
sessionList.add(session);
// 发送上线通知
sendInfo(sid, userId, onlineUserList.size(), "上线了~");
} public void sendInfo(String sid, Integer userId, Integer onlineSum, String info) {
// 获取该连接用户信息
User currentUser = ApplicationContextUtil.getApplicationContext().getBean(UserMapper.class).selectById(userId);
// 发送通知
MsgVO msg = new MsgVO();
msg.setCount(onlineSum);
msg.setUserId(userId);
msg.setAvatar(currentUser.getAvatar());
msg.setMsg(currentUser.getNickName() + info);
// json对象转字符串
String text = JSONObject.toJSONString(msg);
onMessage(sid, userId, text);
} /**
* 关闭连接调用的方法,群成员退出
*
* @param session
* @param sid
*/
@OnClose
public void onClose(Session session, @PathParam("sid") String sid, @PathParam("userId") Integer userId) {
List<Session> sessionList = groupMemberInfoMap.get(sid);
sessionList.remove(session);
Set<Integer> onlineUserList = onlineUserMap.get(sid);
onlineUserList.remove(userId);
// 发送离线通知
sendInfo(sid, userId, onlineUserList.size(), "下线了~");
} /**
* 传输消息错误调用的方法
*
* @param error
*/
@OnError
public void OnError(Throwable error) {
log.info("Connection error");
}
}

4、websocket 消息显示类

@Data
@ApiModel(description = "websocket消息内容")
public class MsgVO { @ApiModelProperty(value = "用户id")
private Integer userId; @ApiModelProperty(value = "用户名")
private String username; @ApiModelProperty(value = "用户头像")
private String avatar; @ApiModelProperty(value = "消息")
private String msg; @ApiModelProperty(value = "在线人数")
private int count; }

5、前端页面

温馨小提示:当用户登录成功之后,可以发起websocket连接,存在store中...

下面只是单页面的简单实现

<template>
<div class="chat-box">
<header>聊天室 (在线:{{count}}人)</header>
<div class="msg-box" ref="msg-box">
<div
v-for="(i,index) in list"
:key="index"
class="msg"
:style="i.userId == userId?'flex-direction:row-reverse':''"
>
<div class="user-head">
<img :src="i.avatar" height="30" width="30" :title="i.username">
</div>
<div class="user-msg">
<span :style="i.userId == userId?' float: right;':''" :class="i.userId == userId?'right':'left'">{{i.content}}</span>
</div>
</div>
</div>
<div class="input-box">
<input type="text" ref="sendMsg" v-model="contentText" @keyup.enter="sendText()" />
<div class="btn" :class="{['btn-active']:contentText}" @click="sendText()">发送</div>
</div>
</div>
</template> <script>
export default {
data() {
return {
ws: null,
count: 0,
userId: this.$store.getters.id, // 当前用户ID
username: this.$store.getters.name, // 当前用户昵称
avatar: this.$store.getters.avatar, // 当前用户头像
list: [], // 聊天记录的数组
contentText: "" // input输入的值
};
},
mounted() {
this.initWebSocket();
},
destroyed() {
// 离开页面时关闭websocket连接
this.ws.onclose(undefined);
},
methods: {
// 发送聊天信息
sendText() {
let _this = this;
_this.$refs["sendMsg"].focus();
if (!_this.contentText) {
return;
}
let params = {
userId: _this.userId,
username: _this.username,
avatar: _this.avatar,
msg: _this.contentText,
count: _this.count
};
_this.ws.send(JSON.stringify(params)); //调用WebSocket send()发送信息的方法
_this.contentText = "";
setTimeout(() => {
_this.scrollBottm();
}, 500);
},
// 进入页面创建websocket连接
initWebSocket() {
let _this = this;
// 判断页面有没有存在websocket连接
if (window.WebSocket) {
var serverHot = window.location.hostname;
let sip = '房间号'
// 填写本地IP地址 此处的 :9101端口号 要与后端配置的一致!
var url = 'ws://' + serverHot + ':9101' + '/groupChat/' + sip + '/' + this.userId; // `ws://127.0.0.1/9101/groupChat/10086/聊天室`
let ws = new WebSocket(url);
_this.ws = ws;
ws.onopen = function(e) {
console.log("服务器连接成功: " + url);
};
ws.onclose = function(e) {
console.log("服务器连接关闭: " + url);
};
ws.onerror = function() {
console.log("服务器连接出错: " + url);
};
ws.onmessage = function(e) {
//接收服务器返回的数据
let resData = JSON.parse(e.data)
_this.count = resData.count;
_this.list = [
..._this.list,
{ userId: resData.userId, username: resData.username, avatar: resData.avatar, content: resData.msg }
];
};
}
},
// 滚动条到底部
scrollBottm() {
let el = this.$refs["msg-box"];
el.scrollTop = el.scrollHeight;
}
}
};
</script> <style lang="scss" scoped>
.chat-box {
margin: 0 auto;
background: #fafafa;
position: absolute;
height: 100%;
width: 100%;
max-width: 700px;
header {
position: fixed;
width: 100%;
height: 3rem;
background: #409eff;
max-width: 700px;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
color: white;
font-size: 1rem;
}
.msg-box {
position: absolute;
height: calc(100% - 6.5rem);
width: 100%;
margin-top: 3rem;
overflow-y: scroll;
.msg {
width: 95%;
min-height: 2.5rem;
margin: 1rem 0.5rem;
position: relative;
display: flex;
justify-content: flex-start !important;
.user-head {
min-width: 2.5rem;
width: 20%;
width: 2.5rem;
height: 2.5rem;
border-radius: 50%;
background: #f1f1f1;
display: flex;
justify-content: center;
align-items: center;
.head {
width: 1.2rem;
height: 1.2rem;
}
// position: absolute;
}
.user-msg {
width: 80%;
// position: absolute;
word-break: break-all;
position: relative;
z-index: 5;
span {
display: inline-block;
padding: 0.5rem 0.7rem;
border-radius: 0.5rem;
margin-top: 0.2rem;
font-size: 0.88rem;
}
.left {
background: white;
animation: toLeft 0.5s ease both 1;
}
.right {
background: #53a8ff;
color: white;
animation: toright 0.5s ease both 1;
}
@keyframes toLeft {
0% {
opacity: 0;
transform: translateX(-10px);
}
100% {
opacity: 1;
transform: translateX(0px);
}
}
@keyframes toright {
0% {
opacity: 0;
transform: translateX(10px);
}
100% {
opacity: 1;
transform: translateX(0px);
}
}
}
}
}
.input-box {
padding: 0 0.5rem;
position: absolute;
bottom: 0;
width: 100%;
height: 3.5rem;
background: #fafafa;
box-shadow: 0 0 5px #ccc;
display: flex;
justify-content: space-between;
align-items: center;
input {
height: 2.3rem;
display: inline-block;
width: 100%;
padding: 0.5rem;
border: none;
border-radius: 0.2rem;
font-size: 0.88rem;
}
.btn {
height: 2.3rem;
min-width: 4rem;
background: #e0e0e0;
padding: 0.5rem;
font-size: 0.88rem;
color: white;
text-align: center;
border-radius: 0.2rem;
margin-left: 0.5rem;
transition: 0.5s;
}
.btn-active {
background: #409eff;
}
}
}
</style>

本文案例demo源码

https://gitee.com/zhengqingya/xiao-xiao-su

SpringBoot+Vue+WebSocket 实现在线聊天的更多相关文章

  1. SpringBoot 使用WebSocket打造在线聊天室

    教程: https://www.jianshu.com/p/55cfc9fcb69e https://wallimn.iteye.com/blog/2425666 关于websocket基础普及见:h ...

  2. SpringBoot基于websocket的网页聊天

    一.入门简介正常聊天程序需要使用消息组件ActiveMQ或者Kafka等,这里是一个Websocket入门程序. 有人有疑问这个技术有什么作用,为什么要有它?其实我们虽然有http协议,但是它有一个缺 ...

  3. vue实现简单在线聊天

    vue实现简单在线聊天 引用mui的ui库,ES6的 fetch做网络请求 //html <!DOCTYPE html> <html> <head> <met ...

  4. 使用websocket实现在线聊天功能

    很早以前为了快速达到效果,使用轮询实现了在线聊天功能,后来无意接触了socket,关于socket我的理解是进程间通信,首先要有服务器跟客户端,服务的启动监听某ip端口定位该进程,客户端开启socke ...

  5. 三分钟搭建websocket实时在线聊天,项目经理也不敢这么写

    我们先看一下下面这张图: 可以看到这是一个简易的聊天室,两个窗口的消息是实时发送与接收的,这个主要就是用我们今天要讲的websocket实现的. websocket是什么? websocket是一种网 ...

  6. .NET Core 基于Websocket的在线聊天室

    什么是Websocket 我们在传统的客户端程序要实现实时双工通讯第一想到的技术就是socket通讯,但是在web体系是用不了socket通讯技术的,因为http被设计成无状态,每次跟服务器通讯完成后 ...

  7. 使用WebSocket实现简单的在线聊天室

    前言:我自已在网上找好了好多 WebSocket 制作 在线聊天室的案列,发现大佬们写得太高深了 我这种新手看不懂,所以就自已尝试写了一个在线简易聊天室 (我只用了js 可以用jq ) 话不多说,直接 ...

  8. vue+websocket+express+mongodb实战项目(实时聊天)

    继上一个项目用vuejs仿网易云音乐(实现听歌以及搜索功能)后,发现上一个项目单纯用vue的model管理十分混乱,然后我去看了看vuex,打算做一个项目练练手,又不想做一个重复的项目,这次我就放弃颜 ...

  9. vue+websocket+express+mongodb实战项目(实时聊天)(二)

    原项目地址:[ vue+websocket+express+mongodb实战项目(实时聊天)(一)][http://blog.csdn.net/blueblueskyhua/article/deta ...

随机推荐

  1. 设计模式C++描述----12.享元(Flyweight)模式

    一. 概述 在面向对象系统的设计何实现中,创建对象是最为常见的操作. 这里面就有一个问题:如果一个应用程序使用了太多的对象,就会造成很大的存储开销.特别是对于大量轻量级(细粒度)的对象,比如在文档编辑 ...

  2. 面向云原生的混沌工程工具-ChaosBlade

    作者 | 肖长军(穹谷)阿里云智能事业群技术专家   导读:随着云原生系统的演进,如何保障系统的稳定性受到很大的挑战,混沌工程通过反脆弱思想,对系统注入故障,提前发现系统问题,提升系统的容错能力.Ch ...

  3. 从《国产凌凌漆》看到《头号玩家》,你就能全面了解5G

    2019 年 9 月,移动.联通.电信5G套餐预约总和已突破 1000 万.2019 年 11 月,三大电信运营商将在全国范围内提供携号转网服务.2019 年内,移动将建立 5 万个 5G 基站,联通 ...

  4. Centos6.5 忘记密码解决方法

    问题 原因  : 太久没用centos了  忘记密码了 很尴尬 快照也没说明密码.... 1.重启 centos 在开机启动的时候快速按键盘上的“E”键 或者“ESC”键(如果做不到精准快速可以在启动 ...

  5. CSP2019知识点整理

    也算是接下来二十天的复习计划吧 仅止于联赛难度左右 基础算法 字符串 char[] cstring memset() 输入无& gets(), fgets(stdin, ,); strcmp, ...

  6. Bootstrap布局基础

     1.栅格系统(布局)Bootstrap内置了一套响应式.移动设备优先的流式栅格系统,随着屏幕设备或视口(viewport)尺寸的增加,系统会自动分为最多12列. 我在这里是把Bootstrap中的栅 ...

  7. [考试反思]0819NOIP模拟测试26:荒芜

    这么正式的考试,明天应该就是最后一次了吧 然而..今天,我仍然没能抓住机会 RNBrank1:.skyh还是稳.外校gmk拿走第三. 四五六名都是63-64.第七50.第八39.我和三个并列的是第九. ...

  8. Appium+python自动化(三十九)-Appium自动化测试框架综合实践 - 代码实现(超详解)

    简介 经过一段时间的准备,完善的差不多了,继续分享有关Appium自动化测试框架综合实践.想必小伙伴们有点等不及了吧! driver配置封装 kyb_caps.yaml 配置表 参考代码 platfo ...

  9. elastalter邮件告警

    一:简介 ElastAlert是一个简单的框架,用于通过Elasticsearch中的数据异常警告,峰值或其他感兴趣的模式. 监控类型 "匹配Y时间内有X个事件的地方"(frequ ...

  10. mysql-大量数据的sql查询优化

    1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 2.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉 ...