【Spring Boot】4.1启用websocket服务

1. 添加依赖 (pom.xml)

<dependencies>
    <!-- 
        Spring Boot WebSocket 起步依赖
        提供了对 Java WebSocket API (JSR-360 / Jakarta WebSocket) 的支持。
        包含了 WebSocket 协议处理、会话管理、消息发送等核心功能。
        注意:Spring Boot 3.x 基于 Jakarta EE,因此底层使用的是 jakarta.websocket 包。
    -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>

    <!-- 
        Spring Messaging 模块
        提供了对消息传递模式的支持,特别是 STOMP (Simple Text Oriented Messaging Protocol)。
        使用 @EnableWebSocketMessageBroker 注解时必需,它允许在 WebSocket 上使用 STOMP 子协议。
        STOMP 提供了更高级的抽象,如订阅、发布、消息代理等,比原始 WebSocket API 更易用。
    -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-messaging</artifactId>
    </dependency>
</dependencies>

2. 配置 WebSocket(Java Config)

package com.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

/**
 * WebSocket 配置类
 * 
 * 该类用于配置 Spring Boot 3.x 项目中的 WebSocket 支持,特别是基于 STOMP 协议的通信。
 * 实现了 WebSocketMessageBrokerConfigurer 接口,可以自定义 WebSocket 消息代理的行为。
 * 
 * 关键注解:
 * - @Configuration: 将此类标记为 Spring 配置类,其定义的 Bean 会被 Spring 容器管理。
 * - @EnableWebSocketMessageBroker: 启用 Spring 的 STOMP 消息代理功能。这是使用 STOMP over WebSocket 的核心注解。
 *   它会自动配置必要的基础设施,如消息转换器、STOMP 帧处理、消息代理等。
 */
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    /**
     * 注册 STOMP 协议的端点(Endpoint)
     * 
     * 这个方法定义了客户端如何连接到服务器的 WebSocket 服务。
     * 客户端会通过这个端点建立初始的 HTTP 连接,并在此基础上升级为 WebSocket 连接。
     * 
     * @param registry STOMP 端点注册器,用于注册和配置端点
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws") // 添加一个名为 "/ws" 的端点
                // .setAllowedOrigins("http://localhost:3000", "https://yourdomain.com") // 生产环境:只允许特定来源
                .setAllowedOriginPatterns("*") // 允许所有来源的跨域请求
                // 注意:setAllowedOriginPatterns("*") 在开发阶段方便,但**存在安全风险**。
                // 生产环境中必须替换为具体的、受信任的域名列表,防止跨站请求伪造(CSRF)攻击。
                .withSockJS(); // 启用 SockJS 支持
                // SockJS 是一个浏览器 JavaScript 库,它提供了一个类似 WebSocket 的对象。
                // 当浏览器或网络不支持原生 WebSocket 时(如某些防火墙限制),SockJS 会自动降级到
                // 其他传输方式(如长轮询、iframe 流等),确保应用在各种环境下都能建立"类 WebSocket"连接。
                // 这大大提高了应用的兼容性和健壮性。
    }

    /**
     * 配置消息代理(Message Broker)
     * 
     * 消息代理负责在客户端之间路由和广播消息。Spring 提供了两种主要的代理实现:
     * 1. 简单内存代理 (Simple Broker): 由 Spring 内部实现,适用于单机部署和简单场景。
     * 2. 外部代理 (External Broker): 如 RabbitMQ、ActiveMQ,支持更复杂的路由、持久化、集群等,适用于生产环境。
     * 
     * 此方法配置了使用简单的内存消息代理。
     * 
     * @param registry 消息代理注册器,用于配置消息代理的行为
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        // 启用一个简单的内存消息代理
        // 该代理会监听以 "/topic" 和 "/queue" 开头的目的地(destination)。
        // - "/topic" 前缀通常用于**发布-订阅**(Pub-Sub)模式:发送到 "/topic/greetings" 的消息会被所有订阅该主题的客户端收到(一对多广播)。
        // - "/queue" 前缀通常用于**点对点**(Point-to-Point)模式:发送到 "/queue/tasks" 的消息通常只会被一个消费者处理(如果多个消费者订阅,行为可能取决于代理实现)。
        // 注意:这里配置的前缀是客户端订阅或接收消息时使用的路径。
        registry.enableSimpleBroker("/topic", "/queue");

        // 设置应用的目的地前缀
        // 所有以 "/app" 开头的消息会被路由到带有 @MessageMapping 注解的控制器方法进行处理。
        // 例如,客户端发送一条目的地为 "/app/hello" 的消息,Spring 会查找并调用 @MessageMapping("/hello") 的方法。
        // 这个前缀将“应用处理逻辑”与“消息代理广播”区分开来。
        registry.setApplicationDestinationPrefixes("/app");
    }
}

3. 定义消息模型(POJO)

package com.example.model;

/**
 * 客户端发送的消息模型
 * 表示客户端向服务器发送的请求数据,例如一个问候请求包含用户的名字。
 */
public class HelloMessage {
    // 存储客户端发送的名字
    private String name;

    // 无参构造函数是 Jackson JSON 序列化/反序列化所必需的
    public HelloMessage() {}

    // 带参构造函数,方便创建对象
    public HelloMessage(String name) {
        this.name = name;
    }

    // Getter 方法,供 Jackson 库在序列化时读取属性值
    public String getName() {
        return name;
    }

    // Setter 方法,供 Jackson 库在反序列化 JSON 时设置属性值
    public void setName(String name) {
        this.name = name;
    }
}

/**
 * 服务器发送的响应消息模型
 * 表示服务器处理完请求后,向客户端(或订阅者)广播的响应数据。
 */
public class GreetingMessage {
    // 存储服务器生成的问候语内容
    private String content;

    // 无参构造函数是 Jackson JSON 序列化/反序列化所必需的
    public GreetingMessage() {}

    // 带参构造函数,方便创建对象
    public GreetingMessage(String content) {
        this.content = content;
    }

    // Getter 方法,供 Jackson 库在序列化时读取属性值
    public String getContent() {
        return content;
    }

    // Setter 方法,供 Jackson 库在反序列化 JSON 时设置属性值
    public void setContent(String content) {
        this.content = content;
    }
}

4. 创建消息处理器(Controller)

package com.example.controller;

import com.example.model.GreetingMessage;
import com.example.model.HelloMessage;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

/**
 * WebSocket 消息处理控制器
 * 
 * 该类负责处理从客户端通过 WebSocket 发送过来的消息。
 * 使用 @Controller 注解,使其成为 Spring MVC 控制器,能够处理消息映射。
 */
@Controller // 标记为 Spring 控制器,使其 Bean 能被组件扫描发现
public class GreetingController {

    /**
     * 处理客户端发送的问候消息
     * 
     * 这个方法会被 Spring 框架调用,当有消息发送到 "/app/hello" 目的地时。
     * 
     * @param message 由 Spring 自动反序列化传入的 HelloMessage 对象。
     *                框架会根据消息的 payload(通常是 JSON)和类型信息,自动转换成 HelloMessage 实例。
     * @return 返回一个 GreetingMessage 对象,该对象将被后续的 @SendTo 处理。
     * @throws Exception 可能抛出异常(例如处理延迟时的 InterruptedException)
     * 
     * 关键注解:
     * - @MessageMapping("/hello"): 将此方法映射到目的地 "/app/hello"。
     *   注意:完整的路径是 "应用前缀 + 映射路径" = "/app/hello"。
     *   客户端需要发送消息到这个目的地才能触发此方法。
     * - @SendTo("/topic/greetings"): 将此方法的返回值(GreetingMessage 对象)发送到 "/topic/greetings" 这个目的地。
     *   所有订阅了 "/topic/greetings" 主题的客户端都会收到这个消息。
     *   这实现了"请求-响应-广播"的模式:一个客户端发送请求,服务器处理后,结果广播给所有(或特定)订阅者。
     */
    @MessageMapping("/hello") 
    @SendTo("/topic/greetings") 
    public GreetingMessage greeting(HelloMessage message) throws Exception {
        // 模拟服务器处理业务逻辑需要的时间(例如查询数据库、调用外部服务等)
        Thread.sleep(1000); 

        // 构造响应消息
        return new GreetingMessage("Hello, " + message.getName() + "!");
    }
}

总结(后端要点与注释说明)

  • 依赖清晰websocket 提供协议支持,messaging 提供 STOMP 高级功能。
  • 配置核心@EnableWebSocketMessageBroker 是启用 STOMP 的开关。registerStompEndpoints 定义连接入口,configureMessageBroker 定义消息路由规则(/app 处理,/topic//queue 广播)。
  • 模型简单:POJO 类用于数据传输,需有无参构造和 Getter/Setter 以支持 JSON 序列化。
  • 处理逻辑@MessageMapping 接收请求,@SendTo 发送响应到代理,实现广播。
  • 安全注意:开发时 setAllowedOriginPatterns("*") 方便,生产环境务必替换为具体可信域名
  • 兼容性withSockJS() 提升了在复杂网络环境下的连接成功率。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值