注意事项
1.vue中要下载nojs.websocket
2.maven项目要配置依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
3.启动器要加入这个
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
前端使用vue+element-UI
<template>
<!-- 聊天室 -->
<div class="test3">
<!-- 聊天框 -->
<div class="msg" ref="box">
<!-- 遍历消息 -->
<div v-for="(item,index) in allMsg" :key="index" class="msg-item" >
<!-- 名字 -->
<div :class="item.whoClass">{{item.context.split(":")[0]}}</div>
<br/>
<!-- 信息 -->
<div :class="item.classes">{{item.context.split(":")[1]}}</div>
</div>
</div>
<el-row :gutter="20">
<el-col :span="8" :offset="7">
<!-- 输入消息的框 element-ui的特点按键事件是@keyup.enter.native这样的 -->
<el-input v-model="msg" placeholder="请输入..." maxlength="30" show-word-limit @keyup.enter.native="putMessage"></el-input>
</el-col>
<el-col :span="2" :offset="0">
<!-- 发送按钮 -->
<el-button type="primary" @click="putMessage" round>发送</el-button>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
watch: {
//监听allMsg,当有修改的时候进行div的屏幕滚动,确保能看到最新的聊天
allMsg: function () {
let that = this;
setTimeout(() => {
//加setTimeout的原因:由于vue采用虚拟dom,我每次生成新的消息时获取到的div的scrollHeight的值是生成新消息之前的值,所以造成每次都是最新的那条消息被隐藏掉了
that.$refs.box.scrollTop = that.$refs.box.scrollHeight;
}, 0);
} },
data() {
return {
// 其他人的名字
otherPName:'',
// 自己的名字
userName:'',
// 所有的消息
allMsg:[],
// 本次消息
msg:'',
//这里定义ws就会无效说找不到send(后来解决了不是箭头函数的原因)
socket:''
}
},
created() {
this.userName=prompt("请取一个名字")
if( this.userName!=null&&this.userName!=''&&this.userName!='null'){
// 给定一个地址
var wsUrl="ws://192.168.81.71:8080/chatRoomServer"
//创建与服务器的连接
var ws= new WebSocket(wsUrl)
this.socket=ws
}
//开启连接时触发的事件
ws.onopen= () =>{
//向服务器发送这个userName
ws.send(this.userName)
}
//接收到消息时触发的事件
ws.onmessage= (message)=> {
// 判断服务器传来的消息时谁的
this.otherPName=message.data.split(":")[0]
if(message.data.split(":")[0]=="系统消息"){
// 系统的
this.allMsg.push({classes:"message1",context:message.data,whoClass:"who1"})
}else if(message.data.split(":")[0]==this.userName){
// 本人的
this.allMsg.push({classes:"message3",context:message.data,whoClass:"who2"})
}else{
// 其他人的
this.allMsg.push({classes:"message2",context:message.data,whoClass:"who3"})
}
}
//关闭窗口触发
window.onbeforeunload=() =>{
ws.close();
}
// 异常关闭error时触发
ws.onerror= () =>{
ws.close();
}
},
methods: {
// 发送消息的方法
putMessage(){
// 判断消息
if(this.msg!=''&&typeof(this.msg)!='undefined'){
// 发送给服务器
this.socket.send(this.msg)
this.msg=''
}else{
alert("请您输入要发送的消息")
}
},
},
}
</script>
<style>
.test3 {
text-align: center;
}
.msg {
width: 800px;
height: 560px;
overflow: auto;
padding-top: 5px;
border: 1px solid red;
display: inline-block;
margin-bottom: 6px;
}
.msg-item {
position: relative;
overflow: hidden;
}
/* 系统提示 */
.message1 {
float: center;
display: inline-block;
border-radius: 40px;
background: rgb(169, 231, 43);
color: rgb(117, 81, 65);
padding: 4px 12px;
margin: 0 0 2px 0;
max-width: 70%;
text-align: left;
box-sizing: border-box;
}
.message2 {
float: left;
display: inline-block;
border-radius: 40px;
background: rgb(19, 156, 191);
color: white;
padding: 4px 12px;
margin: 0 0 2px 0;
max-width: 70%;
text-align: left;
box-sizing: border-box;
}
.message3 {
float: right;
display: inline-block;
border-radius: 40px;
background: #3C3D5A;
color: white;
padding: 4px 12px;
margin: 0 0 2px 0;
max-width: 70%;
text-align: left;
box-sizing: border-box;
}
.who1{
color: red;
float: center;
}
.who2{
color: rgb(44, 19, 233);
float: right;
}
.who3{
color: rgb(255, 0, 208);
float: left;
}
</style>
<!-- <div class="test3">
<div class="msg" ref="box">
<div>
<p v-for="i in allMsg" class="list-item" :key="i">
{{i}}
</p>
</div>
</div>
<div class="input-group">
<input type="text" v-model="msg" @keyup.enter="putMessage">
<input type="button" value="发送" @click="putMessage">
</div>
</div> -->
<!-- <div>
<div class="infinite-list-wrapper" style="overflow:auto">
<ul
class="list"
infinite-scroll-disabled="disabled">
<li v-for="i in allMsg" class="list-item" :key="i">{{ i }}</li>
</ul>
<input type="text" v-model="msg" @keyup.enter="putMessage">
<input type="button" value="发送" @click="putMessage">
</div>
</div> -->
<!-- <div>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>三组聊天室</span>
<el-button style="float: right; padding: 3px 0" type="text">操作按钮</el-button>
</div>
<div v-for="o in allMsg" :key="o" class="text item">
{{o}}
</div>
</el-card>
<input type="text" v-model="msg" @keyup.enter="putMessage">
<input type="button" value="发送" @click="putMessage">
</div> -->
后端java代码
package com.czxy;
import org.springframework.stereotype.Component;
import javax.tools.JavaCompiler;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
/**
* @author 1392373019@qq.com
* @version 1.0
* @date 2019/11/7
*/
//异常报错问题 文本信息长度 用户名长度
@ServerEndpoint("/chatRoomServer")
@Component
public class ChatRoomServer {
private boolean firstFlag=true;
private Session session;
private String userName;
//记录连接数
//key代表是session,value代表的是此次连接
private static final HashMap<String,Object> connectMap= new HashMap<String,Object>();
//保存所有用户昵称信息
//key是sessionId,value是用户名
private static final HashMap<String,String> userMap= new HashMap<String,String>();
/**
* 关闭
*/
//javax---session怎么解决
//vue的聊天界面
//网络断开连接时出现的异常
//moment扩展学习内容
@OnError
public void error(Session session, Throwable t) {
/* Remove this connection from the queue */
userMap.remove(session.getId());
connectMap.remove(session.getId());
}
@OnClose
public void close(Session session){
System.out.println("退出");
//当某个用户退出后,对其他用户进行广播
String message="系统消息:"+userMap.get(session.getId())+"退出聊天";
userMap.remove(session.getId());
connectMap.remove(session.getId());
ChatRoomServer client=null;
for (String connectKey : connectMap.keySet()) {
client= (ChatRoomServer) connectMap.get(connectKey);
try {
if (client!=null){
//给对应的web端发送一个文本信息(message)
client.session.getBasicRemote().sendText(message);
}
} catch (Exception e) {
//遇到异常需要关闭
e.printStackTrace();
}
}
}
@OnOpen
public void start(Session session){
System.out.println("连接成功");
this.session=session;
//保存此连接,所有连接都在这个map中
connectMap.put(session.getId(),this);
}
@OnMessage
public void chat(String clientMessage,Session session){
ChatRoomServer client=null;
if(firstFlag){
this.userName=clientMessage;
userMap.put(session.getId(),userName);
//构造发送给客户端的提示信息
String message="系统消息:"+userName+"进入聊天室";
//将消息广播给所有用户
for (String connectKey : connectMap.keySet()) {
client= (ChatRoomServer) connectMap.get(connectKey);
try {
//给对应的web端发送一个文本信息(message)
client.session.getBasicRemote().sendText(message);
} catch (Exception e) {
//遇到异常需要关闭
e.printStackTrace();
}
}
//输入昵称后firstFlag变成false
firstFlag=false;
}else{
String message=userMap.get(session.getId())+":"+clientMessage;
for (String connectKey : connectMap.keySet()) {
client= (ChatRoomServer) connectMap.get(connectKey);
try {
//给对应的web端发送一个文本信息(message)
client.session.getBasicRemote().sendText(message);
} catch (Exception e) {
//遇到异常需要关闭
e.printStackTrace();
}
}
}
}
}