springboot中@ServerEndpoint和@component同时注解的类为什么每次在代码中this都是一个新的实例

问题:
为什么使用了@Component注解,还可以用this来代表不同的连接?
@Component不是单例模式吗?this不是都指向同一个地址吗?这样写真的可以吗?

上@ServerEndpoint代码:
在这里插入图片描述

来,我们直接找chatgpt问问这个问题的答案,说的模棱两可的,上图:
在这里插入图片描述
上图,感觉说的好像对,好像又不对,思来想去还是想不通,最终决定在源码debug一探究竟
经过一番摸索以后,定位到了源码中的关键三步,如下进行图文分析:
模拟一个ws连接,然后打断点
第一步,ws连接进入onopen事件断点,如图可以看到我们的endpointClass已经被找到了,就是我们对应的ScreenWebSocketServer
在这里插入图片描述
第二步,对于这个源码的onOpen方法进行简要分析查看,如下图:
在这里插入图片描述
我们点进去这个pojo = sec.getConfigurator().getEndpointInstance(sec.getEndpointClass());方法查看,如图:
在这里插入图片描述
下面就是最关键的代码调用替换,也就是我们写的代码是在这一步与源码关联上的,如图分析:
1)先记录一下调用之前,这个pojo的内存地址
在这里插入图片描述
2)进入源码的doOnOpen方法,查看并分析其主要代码结构,如下图:

在这里插入图片描述
3)下面就是关键的一步,源码中进行调用springboot容器中使用了@ServerEndPoint类的onopen方法,如果有直接调用,我们的断点也是直接跳到了我们的业务代码中

methodMapping.getOnOpen().invoke(pojo,
                        methodMapping.getOnOpenArgs(
                                pathParameters, session, config));

在这里插入图片描述
为了简要说明,我们将项目中使用了@ServerEndPoint的类统称为websocketEndPoint类(只是为了叙述方便)。

综上所述,@ServerEndPoint注解的类中代码的this指向的就是ws连接的websocketEndPoint类的全新实例,即每次ws连接就是一个新的websocketEndPoint类实例,所以this每次都指向这个新实例。
所以,这里的this与@Component的单例模式无关,可以理解@ServerEndPoint和@component同时使用时,@Component的作用就只是将这个类对应的代码托管给springboot集成的websocket,它并不是单例的,所以可以在@OnOpen,@OnClose中使用this来区分每次不同的连接
Spring Boot中,有三种常用的方式来实现WebSocket: 1. 使用Spring WebSocket注解: 这是最简单最直接的方法。Spring提供了@ServerEndpoint注解,可以用来快速创建WebSocket端点。通过这种方式,你可以在一个简单的Java中定义WebSocket的处理逻辑,包括连接建立、消息接收、连接关闭等事件。 2. 使用STOMP协议: STOMP(Simple/Streaming Text Oriented Messaging Protocol)是一个简单的面向文本的消息传递协议。Spring支持STOMP,可以通过SockJS或原生的WebSocket来使用。这种方式提供了更高级的消息传递功能,如消息代理、订阅/发布模式等。 3. 使用SockJS: SockJS是一个JavaScript库,它提供了WebSocket的模拟功能,以便在不支持原生WebSocket的浏览器中使用。Spring Boot可以通过SockJS来支持WebSocket通信,提供更好的浏览器兼容性。 使用Spring WebSocket注解的示例: ```java import org.springframework.stereotype.Component; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; @Component public class MyWebSocketHandler extends TextWebSocketHandler { @Override public void handleTextMessage(WebSocketSession session, TextMessage message) { // 处理接收到的消息 System.out.println("Received message: " + message.getPayload()); try { // 发送响应消息 session.sendMessage(new TextMessage("Hello from server!")); } catch (IOException e) { e.printStackTrace(); } } @Override public void afterConnectionEstablished(WebSocketSession session) { // 连接建立时的处理逻辑 System.out.println("Connection established"); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { // 连接关闭时的处理逻辑 System.out.println("Connection closed"); } } ``` 在这种情况下,你需要配置WebSocket消息代理: ```java 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; @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { private final MyWebSocketHandler myWebSocketHandler; public WebSocketConfig(MyWebSocketHandler myWebSocketHandler) { this.myWebSocketHandler = myWebSocketHandler; } @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myWebSocketHandler, "/ws").setAllowedOrigins("*"); } } ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值