WebSocket聊天室demo

本文档展示了如何使用SpringBoot、Maven、WebSocket和nginx搭建一个聊天室应用。涵盖了后端服务器配置、前端JavaScript代码以及nginx代理设置。在添加WebSocket依赖后,注意@SpringBootTest注解可能会导致运行时错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringBoot+Maven+前后端分离+WebSocket+nginx

Maven依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

后端代码

WebSocketServer文件:

import com.xad.util.TimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
@ServerEndpoint("/websocket/chat/{roomName}")
public class WebSocketServer {

    // 使用map来收集session,key为roomName,value为同一个房间的用户集合
    // concurrentMap的key不存在时报错,不是返回null
    private static final Map<String, Set<Session>> rooms = new ConcurrentHashMap<>();

    //注入聊天的service方法

    @OnOpen
    public void connect(@PathParam("roomName") String roomName, Session session) {
        log.info("roomName={}", roomName);
        // 将session按照房间名来存储,将各个房间的用户隔离
        if (!rooms.containsKey(roomName)) {
            // 创建房间不存在时,创建房间
            Set<Session> room = new HashSet<>();
            //添加用户
            room.add(session);
            rooms.put(roomName, room);
        } else {
            // 房间已存在,直接添加用户到相应的房间
            rooms.get(roomName).add(session);
        }
        log.info("客户端已连接");
    }

    @OnClose
    public void disConnect(@PathParam("roomName") String roomName, Session session) {
        rooms.get(roomName).remove(session);
        System.out.println("客户端已断开连接");
    }

    @OnMessage
    public void sendMessage(@PathParam("roomName") String roomName, String msg, Session session) {
        //创建时间
        String time = TimeUtil.getNowTime();
        String message;

        for (Session session1 : rooms.get(roomName)) {
            //判断是否发送给自己
            if (session1.equals(session)) {
                //发送给自己
                message = msg;
            } else {
                //发送给别人
                message = msg;
            }

            //可以在此保存数据到数据库
//         注意存储到数据库
//           根据roomId查询用户的全部信息
//        数据库聊天字段
//            你的id,别人的id,message,内容
            
            //发送
            try {
                session1.getBasicRemote().sendText(message);
            } catch (IOException e) {
                log.error("websocket消息发送异常");
                e.printStackTrace();
            }
            log.info("websocket消息发送成功");

        }
    }
}

WebSocketConfig文件:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

前端代码JS部分

websocket.html文件:

	var websocket = null;
    if ('WebSocket' in window) {
        websocket = new WebSocket("ws://域名(IP):20006/demo/websocket/chat/"+roomName);
    } else {
        alert('该浏览器不支持websocket');
    }

    //连接发生错误的回调方法
    websocket.onerror = function () {
        console.log('连接失败');
    };

    //连接成功建立的回调方法
    websocket.onopen = function (event) {
        console.log('建立连接');
    };

    //接收到消息的回调方法
    websocket.onmessage = function (event) {
        console.log('收到消息:' + event.data);
        var str = '<p>' + event.data + '&nbsp;&nbsp;' + date + '</p>';
        $('.message').append(str);
    };

    //连接关闭的回调方法
    websocket.onclose = function () {
        console.log('连接关闭');
    };

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
        websocket.close();
    };

    //关闭连接
    function closeWebSocket() {
        websocket.close();
    }

    //发送消息
    function send() {
        var chat = $('.chat').val();
        if (chat) {
            websocket.send(chat);
        }
        $('.chat').val("");
    }

nginx配置

上面是项目配置,下面是websocket配置

location /demo/ {
		proxy_pass http://localhost:20006;
		proxy_set_header   Host             $host;
		proxy_set_header   X-Real-IP        $remote_addr;
		proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
	}

location /demo/websocket/ {
        proxy_pass http://localhost:20006;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
		
		proxy_connect_timeout 4s; 
        proxy_read_timeout 7200s; 
        proxy_send_timeout 12s;
    }

注:添加websocket依赖后,@SpringBootTest运行可能报错

改为:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值