logo头像
Snippet 博客主题

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

<java.version>17</java.version>



com.alibaba
fastjson
2.0.32



org.springframework.boot
spring-boot-starter-websocket


org.springframework.boot
spring-boot-starter-tomcat




cn.hutool
hutool-all
5.8.9


org.apache.tomcat.embed
tomcat-embed-websocket
10.1.20

    <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()+”进入了群聊
“);
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 前端代码

Title

安卓学习教程公众号

微信打赏

祝你事业顺心,富贵吉祥,赞赏鼓励