赞
踩
1.引入Websocket依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.配置websocket
@ServerEndpoint(value = "/chat/{fromUser}") @Component public class MyWebsocket { private static Logger log = LoggerFactory.getLogger(MyWebsocket.class); private Session session; /** * 在线用户列表 */ public static Map<String, Session> sessionPool = new HashMap(); @OnOpen public void onOpen(Session session, @PathParam(value = "fromUser") String fromUser) { this.session = session; sessionPool.put(fromUser, session); System.out.println(fromUser + "【websocket消息】有新的连接,总数为:" + sessionPool.size()); } @OnClose public void onClose() { sessionPool.remove(this); System.out.println("【websocket消息】连接断开,总数为:" + sessionPool.size()); } @OnMessage public void onMessage(String msg) { log.info("【websocket消息】收到客户端消息:" + msg); String resoult = msg; Map<String, Object> map = JsonUtils.toMap(msg); String toUser = (String) map.get("toUser"); String ms = (String) map.get("msg"); String account = (String) map.get("fromUser"); sendOneMessage(account, toUser, ms); } /** * 此为单点消息 */ public void sendOneMessage(String account, String userName, String message) { try { log.info("【websocket消息】单点消息:" + message); Session session = sessionPool.get(userName); sessionPool.get(userName); try { //将信息保存到message表中 Record record=new Record(); record.set("date",TimeUtils.getCurrentTime()); record.set("touser",userName); record.set("fromuser",account); record.set("type","test"); record.set("message",message); Db.save("message","id",record); } catch (Exception e) { log.info(e.getMessage()); } ChatMessage chatMessage = new ChatMessage(); chatMessage.setToUser(userName); chatMessage.setMsg(message); chatMessage.setFromUser(account); chatMessage.setType("test"); String time = TimeUtils.getCurrentTime(); chatMessage.setTime(time); String s = JsonUtils.toJSONString(chatMessage); if (session != null) { session.getAsyncRemote().sendText(s); } } catch (Exception e) { e.printStackTrace(); } } }
1.完整代码chat.vue
<template> <div> <!--弹出层查看用户历史发送的消息 --> <el-dialog title="历史消息" :visible.sync="dialogFormVisible" width="900px" top="200px" > <el-table :data="tableData" height="250" border style="width: 100%"> <el-table-column prop="date" label="日期" width="180"> </el-table-column> <el-table-column prop="fromuser" label="发送者" width="180"> </el-table-column> <el-table-column prop="touser" label="接收者"> </el-table-column> <el-table-column prop="message" label="信息"> </el-table-column> </el-table> </el-dialog> <el-row type="flex" justify="center"> <el-col :md="14"> <el-card :body-style="{ padding: '10px' }" style="background-color: #E8E8E8; border: 1px solid #DDDDDD; border-bottom: 0;" > <div style="height: 20px;"> <div style="width: 20px; height: 20px; background-color: #DF7065; border-radius: 50%; float: left;" @click="webSokcetClose()" ></div> <div style="width: 20px; height: 20px; background-color: #E6BB46; border-radius: 50%; float: left; margin-left: 10px;" ></div> <div style="width: 20px; height: 20px; background-color: #5BCC8B; border-radius: 50%; float: left; margin-left: 10px;" ></div> <div> <el-button style="margin-left: 10px;" size="mini" type="success" icon="el-icon-check" circle @click="getMessage()" ></el-button> </div> </div> </el-card> <el-card :body-style="{ padding: '0' }" style="border: 1px solid #DDDDDD; border-top: 0;" > <el-row> <el-col :md="6" style=" height: 600px; border-right: 2px solid #DDDDDD; overflow: auto;" > <el-card :body-style="{ 'padding-top': '11px', 'padding-bottom': '12px', 'padding-left': '10px', 'padding-right': '12px' }" shadow="never" > <div> <el-input size="mini" placeholder="请输入内容" v-model="input1" > </el-input> </div> </el-card> <div v-for="item in listUser" :key="item.id"> <a href="javascript:void(0);" @click="toggleChat(item.account)"> <el-card :body-style="{ padding: '5px 10px' }" shadow="never"> <el-row> <el-col :span="7"> <el-image style="width: 40px; height: 40px; border-radius: 50%;" src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg" fit="cover" ></el-image> </el-col> <el-col :span="17"> <h4 class="m-0" style="color: #666666; font-size: 15px;" > {{ item.account }} </h4> <p style="color: #999999; font-size: 12px; margin: 0; margin-top: 3px;" class="limitTitleDirectory" > 这个家伙很懒,什么也没有留下。 </p> </el-col> </el-row> </el-card> </a> </div> </el-col> <el-col :md="18"> <div v-show="toUser !== '游客'"> <el-card :body-style="{ padding: '15px' }" shadow="never"> <div class="text-center"> <p class="m-0">{{ toUser }}</p> </div> </el-card> <el-card :body-style="{ padding: '5px' }" shadow="never"> <div v-for="item in this.listUser" :key="item.id" v-show="toUser === item.account" :id="item.account" style="height: 327px; overflow: auto;" ></div> </el-card> <el-input type="textarea" :rows="5" v-model="input" @keyup.enter.native="webSokcetSend()" style="margin-top:60px" ></el-input> </div> <div v-show="toUser === '游客'"> <div style="text-align: center; line-height: 600px; background-color: #f3f3f3;" > <p style="margin: 0; font-size: 22px; color: #909399;"> 没有会话消息 </p> </div> </div> </el-col> </el-row> </el-card> </el-col> </el-row> </div> </template> <script> import { getOnlineuser } from "@/api/chat"; import { formatTime } from "@/utils/TimeUtils"; import { getMessage } from "@/api/chat"; export default { name: "mac", data() { return { input: "", input1: "", //在线人数 listUser: [], webSocket: "", fromUser: "游客", toUser: "游客", tableData: "", dialogFormVisible: false //弹出层默认为关闭 }; }, created() { //得到在线人数 getOnlineuser("/ws/getOnlineuser").then(res => { if (res.code === 200) { this.listUser = res.data; } else if (res.code === 500) { this.$message(res.data); } }); this.fromUser = localStorage.getItem("username"); }, mounted() { if (document.cookie === "") { this.webSokcetClose(); } else { } //配置websocket服务器地址 this.webSocket = new WebSocket("ws://localhost:8001/chat/" + this.fromUser); this.initWebSocket(); }, methods: { initWebSocket() { this.webSocket.onerror = this.onError; // 通讯异常 this.webSocket.onopen = this.onOpen; // 连接成功 this.webSocket.onmessage = this.onMessage; // 收到消息时回调 this.webSocket.onclose = this.onClose; // 连接关闭时回调 }, onError() { console.log("通讯异常"); }, onOpen() { console.log("通讯开始"); }, onMessage(event) { console.log(event.data); let data = JSON.parse(event.data); // console.log(data); if (data.list !== undefined) { let list = data.list; for (let i = 0; i < list.length; i++) { if (list[i] === this.fromUser) { list.splice(i, 1); } } this.listUser = list; } this.messageDiv(event.data); console.log(event.data); }, onClose() { console.log("通讯关闭"); }, webSokcetSend() { var now = new Date(); var strnow = formatTime(now); /* * 发送消息 * */ let message = JSON.stringify({ fromUser: this.fromUser, toUser: this.toUser, msg: this.input, time: this.strnow }); this.webSocket.send(message); this.input = ""; this.messageDiv(message); }, webSokcetClose() { }, toggleChat(toUser) { this.toUser = toUser; }, messageDiv(data1) { let data = JSON.parse(data1); let div = document.createElement("div"); let p1 = document.createElement("p"); let p = document.createElement("p"); if (data.time == null) { data.time = formatTime(new Date()); } p1.innerHTML = data.fromUser + " " + data.time; debugger; if (data.fromUser !== "系统通知") { if (data.type !== undefined) { /* * data.type !== undefined * 说明这是接收到消息 * 把值插到发送者的div * */ // let fromUser = document.getElementById("test"); let fromUser = document.getElementById(data.fromUser); p.innerHTML = "收到:" + data.msg; div.style = "width: 500px; float: left; margin-left: 15px; margin-top:10px; "; p1.style = "font-size: 15px; margin-bottom: 0; margin-top: 0; float: left; font-weight: 500; "; p.style = "padding: 10px; background-color: #F1F1F1; margin-top: 25px; margin-bottom: 10px; word-wrap : break-word; "; div.appendChild(p1); div.appendChild(p); fromUser.appendChild(div); fromUser.scrollTop = fromUser.scrollHeight; if (fromUser.style.display === "none") { // console.log("有新的消息未查看!"); this.$message("收到新的消息"); } } else { /* * 说明这是发送消息 * 把值插到接收者的div * */ // let toUser = document.getElementById("test"); let toUser = document.getElementById(data.toUser); p.innerHTML = "发出:" + data.msg; div.style = "width: 500px; float: right; margin-right: 15px; margin-top: 10px;"; p1.style = "font-size: 15px; margin-bottom: 0; margin-top: 0; float: right; font-weight: 500;"; p.style = "padding: 10px; background-color: #9FE86C; margin-top: 25px; margin-bottom: 10px; word-wrap : break-word;"; div.appendChild(p1); div.appendChild(p); toUser.appendChild(div); toUser.scrollTop = toUser.scrollHeight; } } }, //获得历史消息 getMessage() { getMessage("/ws/getMessage").then(res => { if (res.code === 200) { this.dialogFormVisible = true; this.tableData = res.data; } else if (res.code === 500) { this.$message(res.data); } }); } }, beforeRouteEnter(to, from, next) { document .querySelector("body") .setAttribute("style", "background-color: #F9F9F9"); next(); }, beforeRouteLeave(to, from, next) { // 去除背景色 document.querySelector("body").setAttribute("style", ""); next(); } }; </script> <style scoped> .limitTitleDirectory { width: 120px; /* 限制文本宽度 */ overflow: hidden; /* 超出的文本隐藏 */ text-overflow: ellipsis; /* 溢出的文本内容用 ... 代替 */ white-space: nowrap; /* 溢出不换行*/ } element.style { padding-left: 10px; } .el-menu-item { font-size: 14px; color: #303133; padding: 0 10px; cursor: pointer; -webkit-transition: border-color 0.3s, background-color 0.3s, color 0.3s; transition: border-color 0.3s, background-color 0.3s, color 0.3s; -webkit-box-sizing: border-box; box-sizing: border-box; } /*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/ ::-webkit-scrollbar { width: 5px; /*滚动条宽度*/ height: 5px; /*滚动条高度*/ } /*定义滚动条轨道 内阴影+圆角*/ ::-webkit-scrollbar-track { /*-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);*/ border-radius: 10px; /*滚动条的背景区域的圆角*/ /*background-color: red;!*滚动条的背景颜色*!*/ } /*定义滑块 内阴影+圆角*/ ::-webkit-scrollbar-thumb { border-radius: 10px; /*滚动条的圆角*/ /*-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);*/ background-color: #b8b8bc; /*滚动条的背景颜色*/ } .el-col-md-14 { width: 80%; } .el-scrollbar { height: 100%; } </style>
实现效果
源码地址:
https://gitee.com/Marlon_Brando
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。