SpringBoot 结合 WebSocket 实现聊天功能

目录

一、WebSocket  介绍

二、源码

2.1 pom.xml

2.2 WebSocket配置类,用于配置WebSocket的相关设置

 2.3 自定义WebSocket处理器类,用于处理WebSocket的生命周期事件

2.4 自定义WebSocket握手拦截器,用于增强WebSocket的握手过程

 2.5 SessionBean类用于封装与WebSocket会话相关的数据

2.6 前端代码

三、界面效果


一、WebSocket  介绍

WebSocket 是一种网络通信协议,用于在单个 TCP 连接上进行全双工通信。它具有实时性、双向通信、低开销和跨域支持等特点,适用于实时聊天、在线游戏等应用场景。在实际应用中,通常与前端技术结合使用,通过 WebSocket API 来实现实时数据的传输和处理。

二、源码

代码结构

2.1 pom.xml

   <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.32</version>
        </dependency>
        <!-- websocket消息推送 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.9</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-websocket</artifactId>
            <version>10.1.20</version>
        </dependency>



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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

2.2 WebSocket配置类,用于配置WebSocket的相关设置

package com.by.config;
 

import jakarta.annotation.Resource;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
 

/**
 * @author 黄远超
 */
@Configuration
@EnableWebSocket
public class MyWsConfig implements WebSocketConfigurer {
    @Resource
    MyWsHandler myWsHandler;
    @Resource
    MyWsInterceptor myWsInterceptor;
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myWsHandler,"/myWs1")
                .addInterceptors(myWsInterceptor)
                .setAllowedOrigins("*");
    }
    //访问的位置,设置拦截器,设置拦截范围
}

 2.3 自定义WebSocket处理器类,用于处理WebSocket的生命周期事件

package com.by.config;
 
import cn.hutool.core.text.StrBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.server.Session;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
 
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
 
/**
    物理程序
 */
@Component
@Slf4j
public class MyWsHandler extends AbstractWebSocketHandler {
    private static Map<String,SessionBean> sessionBeanMap;
    private static AtomicInteger clientIdMaker;
    private static StringBuffer stringBuffer;
    //初始化
    static {
        sessionBeanMap = new ConcurrentHashMap<>();
        clientIdMaker = new AtomicInteger(0);
        stringBuffer = new StringBuffer();
    }
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);
        SessionBean sessionBean = new SessionBean(session, clientIdMaker.getAndIncrement());
        sessionBeanMap.put(session.getId(),sessionBean);
        log.info(sessionBeanMap.get(session.getId()).getClientId()+"建立连接");
        stringBuffer.append(sessionBeanMap.get(session.getId()).getClientId()+"进入了群聊<br/>");
        sendMessage(sessionBeanMap);
    }
 
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        super.handleTextMessage(session, message);
        log.info(sessionBeanMap.get(session.getId()).getClientId()+":"+message.getPayload());
        stringBuffer.append(sessionBeanMap.get(session.getId()).getClientId()+":"+message.getPayload()+"<br/>");
        sendMessage(sessionBeanMap);
    }
    //异常时
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        super.handleTransportError(session, exception);
        if (session.isOpen()){
            session.close();
        }
        sessionBeanMap.remove(session.getId());
    }
 
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
        int clientId = sessionBeanMap.get(session.getId()).getClientId();
        sessionBeanMap.remove(session);
        log.info(clientId+"关闭了连接");
        stringBuffer.append(clientId+"退出了群聊<br/>");
        sendMessage(sessionBeanMap);
    }
 
    public void sendMessage(Map<String,SessionBean> sessionBeanMap){
        for(String key:sessionBeanMap.keySet()){{
            try {
                sessionBeanMap.get(key).getWebSocketSession().sendMessage(new TextMessage(stringBuffer.toString()));
            } catch (IOException e) {
                log.info("出错啦");
            }
        }}
    }
 
//    //定时任务
//    @Scheduled(fixedDelay = 2000)//多少秒执行1次
//    public void sendMessage() throws IOException {
//        for (String key:sessionBeanMap.keySet()){
//            sessionBeanMap.get(key).getWebSocketSession().sendMessage(new TextMessage(":心跳"));
//        }
//    }
}

2.4 自定义WebSocket握手拦截器,用于增强WebSocket的握手过程

package com.by.config;
 
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
 
import java.util.Map;
 

/**
 * @author 黄远超
 */
@Component
@Slf4j
public class MyWsInterceptor extends HttpSessionHandshakeInterceptor {
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        return super.beforeHandshake(request, response, wsHandler, attributes);
    }
 
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
        super.afterHandshake(request, response, wsHandler, ex);
    }
}

 2.5 SessionBean类用于封装与WebSocket会话相关的数据

package com.by.config;

import jakarta.websocket.Session;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.web.server.WebSession;
import org.springframework.web.socket.WebSocketSession;
 

/**
 * @author 黄远超
 */
/**
 * SessionBean类用于封装与WebSocket会话相关的数据。
 *  webSocketSession 代表一个WebSocket会话的对象,用于与客户端进行双向通信。
 *  clientId 客户端的唯一标识符,用于区分不同的客户端连接。
 */
@Data
@AllArgsConstructor
public class SessionBean {
    private WebSocketSession webSocketSession; // WebSocket会话对象
    private Integer clientId; // 客户端ID
}

2.6 前端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p style="border: 1px solid black;width: 400px;height: 600px" id="talkMsg"></p>
<input id="message" />
<button id="sendBtn" onclick="sendMsg()">发送</button>
</body>
<script>
    let ws = new WebSocket("ws://localhost:8080/myWs1")
    ws.onopen=function (){
    }
    ws.onmessage=function (message) {
        document.getElementById("talkMsg").innerHTML = message.data
    }
    function sendMsg() {
        ws.send(document.getElementById("message").value)
        document.getElementById("message").value=""
    }
</script>
</html>

三、界面效果

访问 http://localhost:8080/Chat.html

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
基于SpringBoot+Vue开发的网页版聊天室系统源码+项目说明+sql数据库(前端+后端).zip 【优质项目推荐】 1.项目代码功能经验证ok,确保稳定可靠运行。欢迎下载使用!在使用过程中,如有问题或建议,请及时私信沟通,帮助解答。 2.项目主要针对各个计算机相关专业,包括计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师或企业员工使用。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为毕设、课程设计、大作业、项目初期立项演示等用途。 4.如果基础还行,或热爱钻研,可基于此项目进行二次开发,DIY其他不同功能。 基于SpringBoot+Vue开发的网页版聊天室系统源码+项目说明+sql数据库(前端+后端).zip 微言聊天室是基于前后端分离,采用SpringBoot+Vue框架开发的网页版聊天室。 使用了Spring Security安全框架进行密码的加密存储和登录登出等逻辑的处理,以WebSocket+Socket.js+Stomp.js实现消息的发送与接收,监听。搭建FastDFS文件服务器用于保存图片,使用EasyExcel导出数据,使用Vue.js结合Element UI进行显示弹窗和数据表格分页等功能,以及整个系统的界面进行UI设计,并且使用MyBatis结合数据库MySQL进行开发。最后使用了Nginx进行部署前后端分离项目。 功能实现:群聊,单聊,邮件发送,emoji表情发送,图片发送,用户管理,群聊记录管理,Excel的导出。 项目预览地址:http://www.javahai.top/index.html ## 项目技术栈 ### 后端技术栈 1. Spring Boot 2. Spring Security 3. MyBatis 4. MySQL 5. WebSocket 6. RabbitMQ 7. Redis ### 前端技术栈 1. Vue 2. ElementUI 3. axios 4. vue-router 5. Vuex 6. WebSocket 7. vue-cli4 ... ## 项目预览图 客户端界面-群聊主界面 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201108163850583.png) 客户端界面-私聊界面 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2020110816390059.png) 管理端界面-用户管理 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201108163906854.png) 管理端界面-群聊消息管理 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201108163912953.png) ## 部署流程 1. clone 项目到本地 2. 在本地 MySQL 中创建一个空的数据库 subtlechat,在该数据库中运行提供的数据库脚本subtlechat.sql,完成表的创建和数据的导入。 3. 提前准备好Redis,在项目中的mail模块的 application.yml 文件中,将 Redis 配置改为自己的。 4. 提前准备好RabbitMQ,在项目中的mail模块的 application.yml 文件中和web模块中的 application-dev.properties,将 RabbitMQ 的配置改为自己的。 5. 注册邮箱的授权码,在项目中的mail模块的 application.yml 文件中填入 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201108165225396.png) 6. 搭建fastdfs服务器,fastdfs-client.properties文件改成自己的。 7. 在 IntelliJ IDEA 中打开subtlechat项目,先启动 mail模块,再启动web模块。 8. 启动vue项目。
好的,下面是springboot结合websocket实现聊天的步骤: 1. 添加websocket依赖 在pom.xml中添加以下依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2. 创建websocket配置类 创建一个配置类,用于注入websocket相关的bean: ``` @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "/myHandler").setAllowedOrigins("*"); } @Bean public MyHandler myHandler() { return new MyHandler(); } } ``` 其中,`MyHandler`是自定义的websocket处理器,`/myHandler`是websocket的访问路径,`setAllowedOrigins("*")`是设置允许跨域访问。 3. 创建websocket处理器 创建一个websocket处理器,用于处理websocket连接、消息接收、消息发送等操作: ``` public class MyHandler extends TextWebSocketHandler { private static final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { sessions.add(session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { String payload = message.getPayload(); for (WebSocketSession s : sessions) { s.sendMessage(new TextMessage(payload)); } } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { sessions.remove(session); } } ``` 其中,`sessions`用于保存所有连接的websocket会话,`afterConnectionEstablished`方法在websocket连接建立时被调用,`handleTextMessage`方法用于处理消息接收并发送给所有会话,`afterConnectionClosed`方法在websocket连接关闭时被调用。 4. 创建websocket前端页面 在前端页面中添加websocket的连接和消息发送代码: ``` var socket = new WebSocket("ws://localhost:8080/myHandler"); socket.onmessage = function(event) { console.log(event.data); }; function sendMessage() { socket.send($("#message").val()); $("#message").val(""); } ``` 其中,`ws://localhost:8080/myHandler`是websocket的连接地址,`socket.onmessage`用于接收到新消息时执行的代码,`sendMessage`用于发送新消息。 5. 运行程序并测试 启动springboot应用程序,访问前端页面,并在多个浏览器窗口中测试发送消息的功能。 以上就是springboot结合websocket实现聊天的全部步骤,希望能帮助到你。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天的接口写完了吗?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值