Springboot使用WebSocket发送消息

1. 创建springboot项目,引入spring-boot-starter-websocket依赖

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

完整项目依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.9</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.mutest</groupId>
    <artifactId>websocket-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>websocket-demo</name>
    <description>websocket demo</description>
    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2. 对websocket进行配置config
registerWebSocketHandlers()方法参数是WebSocketHandlerRegistry 。调用WebSocketHandlerRegistry 的addHandler方法传递处理器和路径。处理器参数是上一步创建的TextWebSocketHandler 的子类。路径是客户端调用时跟在端口后的路径。再调用WebSocketHandlerRegistry 的setAllowedOrigins方法传递星号,允许跨域访问。

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Autowired
    private MyWsHandler myWsHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry
                .addHandler(myWsHandler, "myWs")
                //允许跨域
                .setAllowedOrigins("*");
    }
}

WebSocketHandlerRegistry
addHandler()方法第一个传输传递处理器,第一个参数传递路径
setAllowedOrigins()方法设置允许源,传递星号,否则跨域。

3.定义处理器MyWsHandler

@Component
@Slf4j
public class MyWsHandler extends AbstractWebSocketHandler {

    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        log.info("建立ws连接");
        WsSessionManager.add(session.getId(), session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 接收客户端/浏览器端的消息 message.getPayload()消息体
        String payload = message.getPayload();
        log.info("server 接收到客户端/浏览器端的消息 " + payload);
        log.info("发送文本消息");
        //服务端准备给客户端/浏览器端发送消息
        session.sendMessage(new TextMessage("server 发送给的消息 " + payload + ",发送时间:" + LocalDateTime.now().toString()));
    }

    @Override
    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {
        log.info("发送二进制消息");
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("异常处理");
        WsSessionManager.removeAndClose(session.getId());
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        log.info("关闭ws连接");
        WsSessionManager.removeAndClose(session.getId());
    }
}

4. 单播/多播发送消息
在MyWsHandler中,handleTextMessage方法使用的是单播发送消息,如果要给客户端/浏览器端发送广播消息该如何发送呢,只需遍历所有客户端/浏览器端的Session即可,通过Session广播消息。

@Service
@Slf4j
public class WsService {
    /**
     * 发送消息
     *
     * @param session 连接信息
     * @param text    消息
     */
    public void sendMsg(WebSocketSession session, String text) throws IOException {
        session.sendMessage(new TextMessage(text));
    }

    /**
     * 广播消息
     *
     * @param text 消息
     */
    public void broadcastMsg(String text) throws IOException {
        for (WebSocketSession session : WsSessionManager.SESSION_POOL.values()) {
            session.sendMessage(new TextMessage(text));
        }
    }
}

5. 设置定时任务发送广播消息

@Slf4j
@Component
public class MessageJob {
    @Autowired
    WsService wsService;

    /**
     * 每5s发送
     */
    @Scheduled(cron = "0/5 * * * * *")
    public void run() {
        try {
            log.info("推送消息===>" + LocalDateTime.now().toString());
            wsService.broadcastMsg("自动生成消息 " + LocalDateTime.now().toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

6. 管理客户端/浏览器端的Session工具类

@Slf4j
public class WsSessionManager {
    /**
     * 保存连接 session 的地方
     */
    public static ConcurrentHashMap<String, WebSocketSession> SESSION_POOL = new ConcurrentHashMap<>();

    /**
     * 添加 session
     *
     * @param key key
     */
    public static void add(String key, WebSocketSession session) {
        // 添加 session
        SESSION_POOL.put(key, session);
    }

    /**
     * 删除 session,会返回删除的 session
     *
     * @param key key
     * @return WebSocketSession
     */
    public static WebSocketSession remove(String key) {
        // 删除 session
        return SESSION_POOL.remove(key);
    }

    /**
     * 删除并同步关闭连接
     *
     * @param key key
     */
    public static void removeAndClose(String key) {
        WebSocketSession session = remove(key);
        if (session != null) {
            try {
                // 关闭连接
                session.close();
            } catch (IOException e) {
                // todo: 关闭出现异常处理
                e.printStackTrace();
            }
        }
    }

    /**
     * 获得 session
     *
     * @param key key
     * @return WebSocketSession
     */
    public static WebSocketSession get(String key) {
        // 获得 session
        return SESSION_POOL.get(key);
    }
}

完整的项目结构:
在这里插入图片描述
7. 测试
这里,我们使用在线测试工具,测试网址为:https://wstool.js.org/
在这里插入图片描述
客户端发送消息:

在这里插入图片描述

服务端后台收到的消息:
在这里插入图片描述
模拟服务器多播发送消息给客户端,这里我使用两个不同的浏览器去连接服务端:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相关推荐

  1. 使用WebSocket在前端发送消息

    2024-07-11 10:54:06       35 阅读
  2. Springboot+WebSocket实现消息推送

    2024-07-11 10:54:06       26 阅读
  3. Springboot配置websocket,https使用 WebSocket 连接

    2024-07-11 10:54:06       31 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-11 10:54:06       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-11 10:54:06       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-11 10:54:06       58 阅读
  4. Python语言-面向对象

    2024-07-11 10:54:06       69 阅读

热门阅读

  1. 应用TensorFlow简单工作流程

    2024-07-11 10:54:06       22 阅读
  2. 每个账号设置独立的cookie

    2024-07-11 10:54:06       24 阅读
  3. Jinja2模板引擎使用指南

    2024-07-11 10:54:06       29 阅读
  4. 如何做软件需求分析

    2024-07-11 10:54:06       21 阅读
  5. MySQL语句

    2024-07-11 10:54:06       17 阅读
  6. Flask+Layui开发案例教程

    2024-07-11 10:54:06       19 阅读
  7. mysql面试题 Day6

    2024-07-11 10:54:06       25 阅读