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();
            }
        });
    }
}
相关推荐
ZoeLandia7 小时前
WebSocket | 背景 概念 原理 使用 优缺点及适用场景
网络·websocket·网络协议
zquwei16 小时前
SpringCloudGateway+Nacos注册与转发Netty+WebSocket
java·网络·分布式·后端·websocket·网络协议·spring
carterslam1 天前
解决:websocket 1002 connection rejected 426upgrade required
网络·websocket·网络协议
抓住鼹鼠不撒手1 天前
xterm.js结合websocket实现web ssh
前端·javascript·websocket
学前端的小朱1 天前
Echarts实现大屏可视化
websocket·echarts·nodejs·vue3·vite·koa·cors
龙少95433 天前
【Http,Netty,Socket,WebSocket的应用场景和区别】
java·后端·websocket·网络协议·http
m0_748232923 天前
前端在WebSocket中加入Token
前端·websocket·网络协议
等一场春雨3 天前
react websocket 全局访问和响应
前端·websocket·react.js
流穿4 天前
WebSocket vs SSE:实时通信技术的对比与选择
网络·websocket·网络协议·大语言模型·sse
_.Switch4 天前
FastAPI 的进阶应用与扩展技术:异步编程与协程、websocket、celery
网络·数据库·python·websocket·网络协议·性能优化·fastapi