websocket实现简易聊天室

websocket实现简易聊天室

又做了一个关于websocket广播和在线人数统计的练习,实现一个简易的聊天室。

前端vue3

前端里的内容主要包含:

1.css的animation来实现公告从右到左的轮播。

2.websocket的onmessage里对不同消息的处理。

html 复制代码
<template>
  <div class="common-layout">
    <el-container>
      <el-header>
        <el-row>
          <el-col :span="1"><div>公告:</div></el-col>
          <el-col :span="20">
            <div class="scroll-container">
              <div class="text-scroll">
                公告信息
              </div>
            </div>
          </el-col>
          <el-col :span="3" class="paddingleft20">
            在线人数:<span class="spanTip">{{onlineCount}}</span>
          </el-col>
        </el-row>
      </el-header>
      <el-container>
        <el-aside>
          <el-row v-for="(item, index) in onlineUsers" :key="index">
            <span class="onlinespan">{{item}}</span>
            </el-row>
        </el-aside>
        <el-container>
          <el-main v-html="othermessage">
          </el-main>
          <el-footer>
            <el-row>
              <el-col :span="22">
                <el-input v-model="this.message" :rows="2" resize="none" type="textarea" 
                @keyup.enter="sendMessage()"/>
              </el-col>
              <el-col :span="2" class="center">
                <el-button type="primary" @click="sendMessage()">发送</el-button>
              </el-col>
            </el-row>
          </el-footer>
        </el-container>
      </el-container>
    </el-container>
  </div>
</template>

<script >
import { ref } from 'vue';
const socket = new WebSocket('ws://localhost:8080/chartroom');
const othermessage=ref('')
const onlineCount=ref(0)
const onlineUsers=ref([])
const own=ref('')
export default {
  name: 'Chart-Room',
  components: {
  },
  data(){
    return{
      message:'',
      othermessage,
      onlineCount,
      onlineUsers,
      own
    }
  },
  mounted(){
    this.connect();
  },
  unmounted(){
    this.beforeDestroy();
  },
  methods:{
    connect() {
      socket.onopen = function() {
      };
      socket.onmessage = function(event) {
        if(event.data.indexOf('onlineCount:')>-1){
          onlineCount.value=event.data.split(':')[1]
        }else if(event.data.indexOf('onlineUsers:')>-1){
          var userStr=event.data.split(':')[1];
          onlineUsers.value=userStr.split(',')
        }else if(event.data.indexOf('own')>-1){
          own.value=event.data.split(':')[1]
        }else{
          othermessage.value += "<div>"+event.data+"</div>"
        }
      };
      socket.onerror = function(event) {
        console.error('WebSocket error observed:', event);
      };
    },
    beforeDestroy() {
      if (socket) {
          socket.close();
        }
    },
    sendMessage() {
      if (socket.readyState === WebSocket.OPEN) {
        socket.send(own.value+":"+this.message);
        this.message=""
      }
    },
  }
}
</script>

<style scoped>
  .el-header{
    background-color:rgb(164, 172, 184);
    color: rgb(252, 252, 252);
    text-align: left;
    padding: 10px 15px;
    height:40px;
  }
  .el-aside{
    background-color:rgb(204, 209, 214);
    width:180px;
    height: 300px;
  }
  .el-main{
    background-color:rgb(246, 250, 253);
    padding: 10px 10px;
    white-space: pre-wrap;
    font-size: 14px;
  }
  .el-footer{
    margin:0px;
    padding:3px 3px;
    background-color:rgb(237, 241, 245);
  }
  .center{
    text-align: center;
    padding: 10px 5px;
  }
  .scroll-container {
    overflow: hidden;
    white-space: nowrap;
    text-align: right;
  }
  .text-scroll {
    display: inline-block;
    /** 实现从右到左的动画效果 */
    animation: scroll-right 30s linear infinite;
  }
  @keyframes scroll-right {
    0% {
      transform: translateX(100%);
    }
    100% {
      transform: translateX(-100%);
    }
  }

  .paddingleft20{
    padding-left: 20px;
  }
  .spanTip{
    color: rgb(252, 229, 179);
  }
  .onlinespan{
    margin:10px;
    color: rgb(85, 106, 128);
  }
</style>

后端java+mongodb

1.config配置

java 复制代码
@Configuration
@EnableWebSocket
public class ChartConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(chartHandler(), "/chartroom")
                .setAllowedOrigins("*"); // 允许跨域
    }

    @Bean
    public ChartHandler chartHandler() {
        return new ChartHandler();
    }
}

2.处理连接成功后增加在线人数、断开连接后减少在线人数以及广播和单独发送消息。

java 复制代码
public class ChartHandler extends TextWebSocketHandler {
    private static final Set<WebSocketSession> sessionsSet = Collections.synchronizedSet(new HashSet<>());

    /**
     * 接收消息
     */
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
        //记录到mongodb
        Map<String, String> map = new HashMap<>();
        map.put("time", new Date().toString());
        String msg=message.getPayload().trim();
        map.put("message", msg.split(":")[1]);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String currentDate = sdf.format(new Date());
        MongoDBUtil.insertContent(currentDate, msg.split(":")[0], map);
        // 发送消息给客户端
        sendMessageToAll(message.getPayload());

    }

    /**
     * 连接后的处理
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessionsSet.add(session);
        sendMessageToAll("onlineCount:" + sessionsSet.size());

        sendMessageToAll("onlineUsers:" + getListUsers());

        session.sendMessage(new TextMessage("own:【游客】"+session.getId().substring(0, 8)));
    }

    /**
     * 获取在线用户列表
     */
    private String getListUsers() {
        List<String> usersList = new ArrayList<>();
        for(WebSocketSession item : sessionsSet){
            String userName="【游客】"+item.getId().substring(0, 8);
            if(!usersList.contains(userName)){
                usersList.add(userName);
            }
        }
        return String.join(",", usersList);
    }

    /**
     * 关闭连接后的处理
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        sessionsSet.remove(session);
        sendMessageToAll("onlineCount:" + sessionsSet.size());

        sendMessageToAll("onlineUsers:" + getListUsers());
    }

    /**
     * 广播发送消息
     */
    private void sendMessageToAll(String message) {
        sessionsSet.forEach(item -> {
            try {
                item.sendMessage(new TextMessage(message));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }
}
相关推荐
一只小白菜~1 小时前
实现实时Web应用,使用AJAX轮询、WebSocket、还是SSE呢??
前端·javascript·websocket·sse·ajax轮询
黑金IT1 天前
WebSocket vs. Server-Sent Events:选择最适合你的实时数据流技术
网络·python·websocket·网络协议·fastapi
Jiaberrr1 天前
如何在微信小程序中实现WebSocket连接
前端·javascript·websocket·微信小程序·小程序
bigcarp2 天前
linux + 宝塔 + django + websocket 部署
linux·websocket·django
weixin_473894773 天前
对WebSocket的理解
网络·websocket·网络协议
乐辞3 天前
WebSocket和HTTP协议有什么区别
websocket·网络协议·http
一直在学习的小白~3 天前
基于React通用的 WebSocket 钩子 useWebSocket
javascript·websocket·react.js
懒人w4 天前
WebSocket 和 HTTP 请求区别
websocket·网络协议·http
秋沐4 天前
Vue3使用Websocket进行跨页面通信
网络·websocket·网络协议
java知路6 天前
tio websocket 客户端 java 代码 工具类
网络·websocket·网络协议