Websocket的两种不同形式

一、java原生websocket

1.1基于标准规范

遵循JSR 356(Java EE 7+),需要应用服务器支持(如Tomcat 8+、Jetty 9+)。

1.2​核心组件

  • 注解驱动​:使用@ServerEndpoint定义服务端端点,通过@OnOpen@OnMessage@OnClose等注解处理事件。
  • 编解码器​:自定义Encoder/Decoder处理消息与对象的转换。
  • 配置类​:通过ServerEndpointConfig.Configurator自定义握手逻辑或端点配置。

1.3​特点

  • 轻量级​:直接操作底层API,适合对协议有精细控制需求的场景。
  • 依赖容器​:需运行在支持Java EE 7+的服务器中,配置相对繁琐。
  • 无高级协议支持​:需自行实现消息路由、订阅等逻辑。

1.4代码 

import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
 
@ServerEndpoint("/chat")
public class ChatEndpoint {
 
    private static final CopyOnWriteArraySet<Session> sessions = new CopyOnWriteArraySet<>();
 
    @OnOpen
    public void onOpen(Session session) {
        sessions.add(session);
        System.out.println(" 新连接:" + session.getId());
        sendMessage(session, "欢迎加入聊天!");
    }
 
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println(" 收到来自 " + session.getId() + " 的消息:" + message);
        // 广播给所有客户端
        for (Session s : sessions) {
            sendMessage(s, "用户 " + session.getId() + " 说: " + message);
        }
    }
 
    @OnClose
    public void onClose(Session session, CloseReason reason) {
        sessions.remove(session);
        System.out.println(" 连接关闭:" + session.getId() + ",原因:" + reason.getReasonPhrase());
    }
 
    @OnError
    public void onError(Session session, Throwable throwable) {
        System.err.println(" 错误发生于连接 " + session.getId() + ": " + throwable.getMessage());
    }
 
    private void sendMessage(Session session, String msg) {
        try {
            session.getBasicRemote().sendText(msg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

二 、​Spring WebSocket

2.1框架集成

Spring Framework 4+提供支持,与Spring MVC、Security等组件深度集成。

2.2​核心组件

  • 配置简化​:通过@EnableWebSocket启用支持,或使用@EnableWebSocketMessageBroker整合STOMP协议。
  • 消息代理​:支持基于内存(如RabbitMQ、ActiveMQ)的消息代理,实现订阅-发布模式。
  • STOMP协议​:通过@MessageMapping路由消息,类似HTTP的REST风格。
  • 拦截器​:提供HandshakeInterceptor处理握手前后逻辑,ChannelInterceptor监控消息通道。

 2.3特点

  • 高层抽象​:简化端点注册和消息处理,支持消息转换(如JSON到对象)。
  • 安全性​:集成Spring Security实现WebSocket的认证与授权。
  • 跨域兼容性​:通过WebSocketTransportRegistration配置跨域和消息限制。
  • 客户端支持​:提供WebSocketClient抽象,兼容多种实现(Tomcat、Jetty等)。

2.4代码 

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
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;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Controller;
import org.springframework.web.socket.messaging.SessionConnectedEvent;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic"); // 消息代理前缀
        config.setApplicationDestinationPrefixes("/app"); // 应用目的前缀
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/chat-websocket") // WebSocket连接端点
                .withSockJS(); // 支持SockJS回退选项
    }
}

@Controller
public class ChatController {
    private final SimpMessagingTemplate messagingTemplate;

    public ChatController(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }

    // 处理客户端发送的消息
    @MessageMapping("/send")  // 接收/app/send的消息
    @SendTo("/topic/chat")    // 广播到所有订阅/topic/chat的客户端
    public String handleMessage(String message) {
        return "用户说: " + message;
    }

    // 监听连接建立事件
    @EventListener
    public void handleWebSocketConnectListener(SessionConnectedEvent event) {
        String sessionId = event.getMessage().getHeaders().get("simpSessionId").toString();
        System.out.println("新连接: " + sessionId);
        
        // 发送欢迎消息到当前客户端
        messagingTemplate.convertAndSendToUser(
            sessionId, 
            "/queue/welcome", 
            "欢迎加入聊天!"
        );
    }

    // 监听连接断开事件
    @EventListener
    public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {
        String sessionId = event.getSessionId();
        System.out.println("连接关闭: " + sessionId);
        
        // 通知其他用户该用户离开
        messagingTemplate.convertAndSend(
            "/topic/chat", 
            "用户 " + sessionId + " 已离开"
        );
    }
}

 

const socket = new SockJS('/chat-websocket');
const stompClient = Stomp.over(socket);

stompClient.connect({}, (frame) => {
    // 订阅广播频道
    stompClient.subscribe('/topic/chat', (message) => {
        console.log('收到广播: ' + message.body);
    });
    
    // 订阅私有欢迎频道
    stompClient.subscribe('/user/queue/welcome', (message) => {
        console.log('系统消息: ' + message.body);
    });
});

// 发送消息到服务端
function sendMessage() {
    stompClient.send("/app/send", {}, "Hello World");
}

 三、二者的区别

特性Java原生WebSocketSpring WebSocket
协议支持仅基础WebSocket,需自行扩展支持STOMP,简化消息路由与广播
开发效率需手动处理会话、路由,代码量较大注解驱动,集成消息代理,开发效率高
安全性需自定义实现无缝整合Spring Security
依赖与兼容性依赖Java EE服务器支持Spring Boot自动配置,跨容器兼容
适用场景轻量级、低延迟或需直接控制协议的场景复杂应用(如聊天、实时通知),需快速集成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值