websocket聊天室

本文最后更新于2022.05.14-17:50,某些文章具有时效性,若有错误或已失效,请在下方留言或联系涛哥

前言

WebSocket ,HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议,其使用简单,应用场景也广泛,不同开发语言都用种类繁多的实现,仅Java体系中,Tomcat,Jetty,Spring等都提供了对WS的API支持。本篇不做理论探究,仅自娱自乐,简单实现网页版的聊天室功能,在实际开发场景中变通使用即可。

代码实现

1,userList.vue

<template>
    <div class="user-list">
				 <ul class="layui-menu" style="margin-top: -1px;">
				    <li v-for="ul in userList" :key="ul.userId">
				      <div class="layui-menu-body-title">
						  {{ul.userName}}
						  <button type="button" class="layui-btn layui-btn-danger">禁言</button>
						  </div>
				    </li>
					
				  </ul>
			</div>
</template>

<script>
import pubsub from 'pubsub-js'
export default {
	name:'UserList',
	data(){
		return{
			userList:[]
		}
	},
	mounted () {
		//收到用户列表
		this.userList=pubsub.subscribe('userList',(nsgNmae,data) => {
				this.userList=data;
			});
	},
	beforeDestroy(){//组件摧毁时触发
	//摧毁掉消息接收者,提高性能
		pubsub.unsubscribe(this.userList);
	}
}
</script>

<style scoped>
    .user-list{
				width: 25%;
				height: 100%;
				float: left;
				/* 垂直滚动条 */
				overflow-y: auto;
				overflow-x: hidden;
				background-color:#A8DADC ;
			}
			.user-list ul li div{
				text-overflow: ellipsis;
				overflow: hidden;
				white-space: nowrap;
			}
			/*滚动条样式*/
			.user-list::-webkit-scrollbar {/*滚动条整体样式*/
				width: 4px;     /*高宽分别对应横竖滚动条的尺寸*/
				height: 4px;
			}
			.user-list::-webkit-scrollbar-thumb {/*滚动条里面小方块*/
				border-radius: 5px;
				-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
				background: rgba(0,0,0,0.2);
			}
			.user-list::-webkit-scrollbar-track {/*滚动条里面轨道*/
				-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
				border-radius: 0;
				background: rgba(0,0,0,0.1);
			}
</style>>

2,Message.vue

<template>
    <div>
        	<div class="msg-title">
					{{msgTitle}}({{uNum}}人在线)
			</div>
			<div class="msg-content">
				<p v-if="initMsg">{{initMsg}}</p>
				<ul ref="message">
					<li v-for="(msg,index) in msgList" :key="index">
						<template v-if="msg.code == 1">
							<span>{{msg.sName}}</span> <span>时间:{{msg.time}}</span>
							<p style="color:green;">{{msg.msg}}</p>
						</template>
						<template v-if="msg.code== 4">
							<span>{{msg.sName}}</span> <span>时间:{{msg.time}}</span>
							<p style="color:red;">{{msg.msg}}</p>
						</template>
						<!-- template 不会显示在页面上 一般搭配if使用 -->
						<template v-if="msg.code == 2">
							<span>时间:{{msg.time}}</span>
							<p>{{msg.sName}}<b>说:</b> <span v-html="msg.msg"></span></p>
						</template>
						<br>
					</li>
				</ul>
			</div>
			<div class="send-msg">
				      <textarea name="desc" placeholder="请输入内容" class="layui-textarea send-content" v-model="msg" @keydown.enter="sendMsg"></textarea>
				<button type="button" class="layui-btn send-btn" @click="sendMsg()" >
					<i class="layui-icon">&#xe609;</i>
						发 送
				</button>
			</div>
    </div>
</template>

<script>
import pubsub from 'pubsub-js'
export default { 
    name:'Message',
    data(){
        return{
			msgTitle:'websocket聊天室',
            msg:'',
			initMsg:'',
			uNum:0,
			msgList:[]
        }
    },
    methods:{
        sendMsg(){
            console.log(this.msg);
			//发给App组件让App组件发给服务器
			 pubsub.publish('sendMsg',this.msg);
             this.msg="";
        }
    },
	mounted(){//所有元素加载完成之后调用
		//创建一个消息接收者
		this.pub=pubsub.subscribe('init',(nsgNmae,data) => {
			this.initMsg=data;
		});
		//接收新用户信息
		this.newUser=pubsub.subscribe('newUser',(nsgNmae,data) => {
			this.msgList.push(data);//在数组后面追加一个对象
			setTimeout(() => {
				this.$refs.message.scrollTop = this.$refs.message.scrollHeight;
			}, 1000);	
		});
		//接收总人数
		this.userNum=pubsub.subscribe('userNum',(nsgNmae,data) => {
			this.uNum=data;
		});
	},
	beforeDestroy(){//组件摧毁时触发
	//摧毁掉消息接收者,提高性能
		pubsub.unsubscribe(this.pub);
		pubsub.unsubscribe(this.newUser);
		pubsub.unsubscribe(this.userNum);
	}
}
</script>

<style scoped>
		
			img{
				width: 100px;
				height: 100px;
			}
			.msg-title{
				width: 75%;
				height: 50px;
				float: left;
				text-align: center;
				font-size: 25px;
				line-height: 50px;
				background-color: #E0FBFC;
			}
			.msg-content{
				width: 75%;
				height: 650px;
				float: left;
				
				 /* 强制换行 */
    			word-wrap: break-word;
				background-color: #fff;
			}
			.msg-content ul{
				width: 100%;
				height: 630px;
				border-top: 1px solid #ccc;
				/* 垂直滚动条 */
				overflow-y: auto;
			}
			/*滚动条样式*/
			.msg-content ul::-webkit-scrollbar {/*滚动条整体样式*/
				width: 4px;     /*高宽分别对应横竖滚动条的尺寸*/
				height: 4px;
			}
			.msg-content ul::-webkit-scrollbar-thumb {/*滚动条里面小方块*/
				border-radius: 5px;
				-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
				background: rgba(0,0,0,0.2);
			}
			.msg-content ul::-webkit-scrollbar-track {/*滚动条里面轨道*/
				-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
				border-radius: 0;
				background: rgba(0,0,0,0.1);
			}
			.send-msg{
				width: 75%;
				height: 200px;
				float: left;
				background-color: #fff;
				position: relative;
			}
			.send-btn{
				position: absolute;
				right: 15px;
				bottom: 15px;;
			}
			.send-content{
				height: 72%;
			}
</style>>

3,App.vue

<template>
    <div class="wechat">
          <UserList/>
          <Message/>
    </div>
</template>

<script>
//引入组件
import UserList from './components/UserList.vue';
import Message from './components/Message.vue';
import pubsub from 'pubsub-js'
export default {
  name: 'App',
  components: {//注册组件
    UserList,
    Message
  },
  mounted(){
    var ws = new WebSocket("ws://localhost:8080/websocket/ChatServer/aaa");
    ws.onopen = function(){//通道建立时触发
          //通过pubsub 消息订阅插件发给message组件  npm install pubsub-js -s
          pubsub.publish('init',"与聊天服务器连接成功");
    }
    ws.onmessage = function(event){//收到服务器发送的消息时触发
        //json字符串转对象
        var data=JSON.parse(event.data);
        if(data.code == 1){//接收有新人连接上来的信息
          pubsub.publish('newUser',data);//把收到的信息发送给message组件
        }else if(data.code == 2){//接收聊天消息
           pubsub.publish('newUser',data);//把收到的信息发送给message组件
           //js去除标签
              var temp = data.msg.replace(/<\/?.+?>/g, "");
              var result = temp.replace(/ /g, "");//result为得到后的内容
            //生成一个随机数,用来控制弹幕的速度
              var speedRan = Math.ceil(Math.random()*10);
              var item={
                 img:'static/imgs/1.jpeg', //图片 
                 info:result, //文字 
                 href:'#', //链接 
                 close:true, //显示关闭按钮 
                 speed:speedRan, //延迟,单位秒,默认6 
              //    bottom:70, //距离底部高度,单位px,默认随机 
                 color:'#fff', //颜色,默认白色 
                 old_ie_color:'#000000', //ie低版兼容色,不能与网页背景相同,默认黑色 
               }
              //控制当弹幕量过大的处理
              if($(".barrage").length < 30){
                  $('body').barrager(item);
              }
        }else if(data.code == 3){//接收聊天室总人数 
           pubsub.publish('userNum',data.uNumber);
        }else  if(data.code == 4){//下线通知
          pubsub.publish('newUser',data);//把收到的信息发送给message组件
        }else  if(data.code == 5){//接收用户列表
          pubsub.publish('userList',data.userMap);//把收到的信息发送给userlist组件
        }
    }
    ws.onclose = function(){//连接断开时触发

    }
    ws.onerror = function(){//通道异常时触发

    }

    //接收消息组件发给App组件
    	this.sendMsg=pubsub.subscribe('sendMsg',(nsgNmae,data) => {
          //页面段websocket发送信息
          ws.send(data);
		});

    //当页面关闭时主动断开连接
    window.onbeforeunload = function(){
      ws.close();
    }
  },
	beforeDestroy(){//组件摧毁时触发
	//摧毁掉消息接收者,提高性能
		pubsub.unsubscribe(this.sendMsg);
	}
}
</script>

<style>
img{
	width: 150px;
	height: 150px;
}
     body{
            background-color: #D8E2DC;
      }
			.wechat{
				width: 65%;
				height: 900px;
				background-color: #fff;
				margin: 0 auto;
			}
</style>>

4,layui

 <link rel="stylesheet" type="text/css" href="static/layui/css/layui.css"/>
    <link rel="stylesheet" href="static/css/barrager.css">
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
		<script src="static/layui/layui.js" type="text/javascript" charset="utf-8"></script>
    <script src="static/js/jquery.barrager.min.js" type="text/javascript" charset="utf-8"></script>

5,在config下的index文件的proxyTable:{}里添加跨域配置

 '/websocket':{
        target:"ws://192.168.1.188",
        changeOrigin:true,
        ws:true,//支持websocket
        pathRewrite:{'^/websocket':''}
      }
阅读剩余
THE END