springboot+websocket实现简单的在线聊天功能

效果如下:

 

 

java实现逻辑:

复制代码
1.引入maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.创建一个服务端
package com.example.demo.controller;

import org.springframework.web.bind.annotation.RestController;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint("/websocket/{name}")
@RestController
public class WebSocketServer {

    //存储客户端的连接对象,每个客户端连接都会产生一个连接对象
    private static ConcurrentHashMap<String,WebSocketServer> map=new ConcurrentHashMap();
    //每个连接都会有自己的会话
    private Session session;
    private String name;
    @OnOpen
    public void open(@PathParam("name") String name, Session session){
        map.put(name,this);
        System.out.println(name+"连接服务器成功");
        System.out.println("客户端连接个数:"+getConnetNum());

        this.session=session;
        this.name=name;
    }
    @OnClose
    public void close(){
        map.remove(name);
        System.out.println(name+"断开了服务器连接");
    }
    @OnError
    public void error(Throwable error){
        error.printStackTrace();
        System.out.println(name+"出现了异常");
    }
    @OnMessage
    public void getMessage(String message) throws IOException {
        System.out.println("收到"+name+":"+message);
        System.out.println("客户端连接个数:"+getConnetNum());

        Set<Map.Entry<String, WebSocketServer>> entries = map.entrySet();
        for (Map.Entry<String, WebSocketServer> entry : entries) {
            if(!entry.getKey().equals(name)){//将消息转发到其他非自身客户端
                entry.getValue().send(message);

            }
        }
    }

    public void send(String message) throws IOException {
        if(session.isOpen()){
           session.getBasicRemote().sendText(message);
        }
    }

    public int  getConnetNum(){
        return map.size();
    }
}
3.一个配置类
@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
    
}
复制代码

//客户端html代码,此处创建2个客户端,一个叫xiaoMing一个叫xiaoHua

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>当前用户xiaoMing</title>
</head>
<style>
    #message{
        width: 50%;
        height: 500px;
        border: 1px solid black;
        background-color: darkgray;

    }

    #inputVal{
        width: 50%;
    }
    input{
        width: 92%;
    }
</style>
<body>
<h1>当前用户xiaoMing</h1>
<div id="message">

</div>
<div id="inputVal">
    <input type="text" name="text">
    <button onclick="send()">发送</button>
</div>

<script>
    var messageEl=document.getElementById("message");
    var inputEl=document.getElementsByTagName("input")[0];
    var websocket=null;
    if('WebSocket' in window){
        websocket=new WebSocket("ws:localhost:2300/websocket/xiaoMing");
    }else {
        alert("浏览器不支持");

    }
    websocket.onopen=function () {
        console.log("webscoket已经连接成功");
        addMessage("webscoket已经连接成功");

    };
    websocket.onclose=function () {
        console.log("webscoket连接失败");
        addMessage("webscoket连接失败");
    };
    websocket.onmessage=function (event) {
        addMessage(event.data);
    };
    websocket.onerror=function () {
        console.log("webscoket连接失败");
        addMessage("webscoket连接失败");
    };
    function addMessage(message) {
        messageEl.innerHTML+=message+"</br>";
    }
    
    function send() {
        websocket.send("xiaoMing:"+inputEl.value);
        messageEl.innerHTML+="我:"+inputEl.value+"</br>";
    }


</script>

</body>
</html>
复制代码
复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>当前用户xiaoHua</title>
</head>
<style>
    #message{
        width: 50%;
        height: 500px;
        border: 1px solid black;
        background-color: darkgray;
    }

    #inputVal{
        width: 50%;
    }
    input{
        width: 92%;
    }
</style>
<body>
<h1>当前用户xiaoHua</h1>
<div id="message">

</div>
<div id="inputVal">
    <input type="text" name="text">
    <button onclick="send()">发送</button>
</div>

<script>
    var messageEl=document.getElementById("message");
    var inputEl=document.getElementsByTagName("input")[0];

    var websocket=null;
    if('WebSocket' in window){
        websocket=new WebSocket("ws:localhost:2300/websocket/xiaoHua");
    }else {
        alert("浏览器不支持");

    }
    websocket.onopen=function () {
        console.log("webscoket已经连接成功");
        addMessage("webscoket已经连接成功");

    };
    websocket.onclose=function () {
        console.log("webscoket连接失败");
        addMessage("webscoket连接失败");
    };
    websocket.onmessage=function (event) {
        addMessage(event.data);
    };
    websocket.onerror=function () {
        console.log("webscoket连接失败");
        addMessage("webscoket连接失败");
    };
    function addMessage(message) {
        messageEl.innerHTML+=message+"</br>";
    }

    function send() {
        websocket.send("xiaoHua:"+inputEl.value);
        messageEl.innerHTML+="我:"+inputEl.value+"</br>";
    }


</script>

</body>
</html>
复制代码

 

posted @   yangxiaohui227  阅读(6518)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类
点击右上角即可分享
微信分享提示