经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring » 查看文章
[超详细]SpringBoot整合WebSocket
来源:cnblogs  作者:护发师兄  时间:2023/8/29 8:47:22  对本文有异议

1. 什么是WebSocket?

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它允许在浏览器和服务器之间进行实时的、双向的通信。相对于传统的基于请求和响应的 HTTP 协议,WebSocket 提供了一种更有效、更实时的通信方式,适用于需要实时更新、实时通知和实时交互的应用。

WebSocket 的一些关键特点包括:

  1. 全双工通信: WebSocket 允许服务器和客户端在同一连接上同时进行双向通信。这意味着服务器可以随时向客户端推送数据,而不必等待客户端发送请求。
  2. 持久连接: WebSocket 连接一旦建立,会一直保持打开状态,不会像传统的 HTTP 连接那样在每次请求和响应之后关闭。这减少了每次连接建立和关闭的开销,使通信更加高效。
  3. 低延迟: 由于连接保持打开状态,WebSocket 通信具有较低的延迟,适用于实时性要求较高的应用,如实时聊天、实时数据更新等。
  4. 少量的数据交换: 与 HTTP 请求和响应相比,WebSocket 数据交换的开销较小。WebSocket 的帧头相对较小,因此有效载荷的比例更高。
  5. 兼容性: 现代浏览器和大多数服务器支持 WebSocket。此外,WebSocket 协议还定义了一个子协议 STOMP(Streaming Text Oriented Messaging Protocol),用于更高级的消息传递和订阅功能。
  6. 安全性: 与其他网络通信协议一样,WebSocket 通信也需要一些安全性的考虑。可以使用加密协议(如 TLS)来保护数据在网络传输中的安全性。

2. 代码实战

2.1 SpringBoot导入依赖

在pom.xml中导入以下依赖,版本由SpringBoot管理

  1. <!-- websocket -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-websocket</artifactId>
  5. </dependency>

2.2 创建配置类

创建WebSocketConfig配置类,并将其注入到Bean容器中

  1. import org.springframework.context.annotation.Bean;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.web.socket.server.standard.ServerEndpointExporter;
  4. @Configuration
  5. public class WebSocketConfig {
  6. @Bean
  7. public ServerEndpointExporter serverEndpointExporter() {
  8. return new ServerEndpointExporter();
  9. }
  10. }

2.3 创建WebSocketServer类

创建WebSocketServer类,并将其注入到Bean容器中

注意:@ServerEndpoint("/WebSocket"),该注解用于配置建立WebSocket连接的路径,可以按需修改。

该类一般拥有以下功能:

  1. WebSocket 端点注册: WebSocket 服务器需要注册一个或多个 WebSocket 端点(Endpoints)。每个端点对应一种处理逻辑,可以处理客户端发送过来的消息,以及向客户端发送消息。这些端点通过注解或配置来定义。
  2. 建立和维护连接: WebSocket 服务器负责监听客户端的连接请求,一旦有客户端连接,服务器会创建一个 WebSocket 会话(Session)来管理这个连接。服务器需要能够维护这些连接,包括打开、关闭、保持心跳等操作。
  3. 消息处理: 一旦客户端连接成功,WebSocket 服务器需要处理客户端发送过来的消息。这可以在 WebSocket 端点中的方法上定义处理逻辑。服务器可以根据不同的业务需求处理不同类型的消息。
  4. 处理异常: 与任何网络通信一样,WebSocket 连接可能会面临各种异常情况,如断开连接、网络问题等。WebSocket 服务器需要能够处理这些异常情况,进行适当的清理和处理。

可以将该类理解为WebSocket生命周期中会调用的方法。

  1. import lombok.extern.slf4j.Slf4j;
  2. import org.springframework.stereotype.Component;
  3. import javax.websocket.*;
  4. import javax.websocket.server.ServerEndpoint;
  5. @Slf4j
  6. @Component
  7. @ServerEndpoint("/WebSocket")
  8. public class WebSocketServer {
  9. private Session session;
  10. @OnOpen
  11. public void onOpen(Session session) {
  12. this.session = session;
  13. WebSocketManager.sentToUser(session, "WebSocket is connected!");
  14. WebSocketManager.addWebSocketServer(this);
  15. log.info("与SessionId:{}建立连接", session.getId());
  16. }
  17. @OnClose
  18. public void onClose() {
  19. WebSocketManager.removeWebSocketServer(this);
  20. log.info("WebSocket连接关闭");
  21. }
  22. @OnMessage
  23. public void onMessage(String message, Session session) {
  24. log.info("来自SessionId:{}的消息:{}", session.getId(), message);
  25. }
  26. @OnError
  27. public void onError(Session session, Throwable error) {
  28. log.error("Session:{}的WebSocket发生错误", session.getId(), error);
  29. }
  30. public Session getSession() {
  31. return session;
  32. }
  33. public String getSessionId() {
  34. return session.getId();
  35. }
  36. }

2.4 创建WebSocketServer管理类

该类用于管理WebSocketServer(其实主要是管理Session),如果不需要发送消息给特定用户,那么无需创建该类,在WebSocketServer类中维护一个类变量即可。

  1. import lombok.extern.slf4j.Slf4j;
  2. import javax.websocket.Session;
  3. import java.util.concurrent.ConcurrentHashMap;
  4. import java.util.concurrent.CopyOnWriteArraySet;
  5. @Slf4j
  6. public class WebSocketManager {
  7. private final static CopyOnWriteArraySet<WebSocketServer> webSocketServerSet = new CopyOnWriteArraySet<>();
  8. private final static ConcurrentHashMap<String, WebSocketServer> webSocketServerMap = new ConcurrentHashMap<>();
  9. public static void addWebSocketServer(WebSocketServer webSocketServer){
  10. if (webSocketServer != null){
  11. webSocketServerSet.add(webSocketServer);
  12. webSocketServerMap.put(webSocketServer.getSessionId(), webSocketServer);
  13. }
  14. }
  15. public static void removeWebSocketServer(WebSocketServer webSocketServer){
  16. webSocketServerSet.remove(webSocketServer);
  17. webSocketServerMap.remove(webSocketServer.getSessionId());
  18. }
  19. /**
  20. * 通过SessionId发送消息给特定用户
  21. * @param
  22. * @param msg
  23. */
  24. public static void sentToUser(String sessionId, String msg){
  25. Session session = webSocketServerMap.get(sessionId).getSession();
  26. sentToUser(session, msg);
  27. }
  28. /**
  29. * 通过Session发送消息给特定用户
  30. * @param session
  31. * @param msg
  32. */
  33. public static void sentToUser(Session session, String msg){
  34. if (session == null){
  35. log.error("不存在该Session,无法发送消息");
  36. return;
  37. }
  38. session.getAsyncRemote().sendText(msg);
  39. }
  40. /**
  41. * 发送消息给所有用户
  42. * @param msg
  43. */
  44. public static void sentToAllUser(String msg){
  45. for (WebSocketServer webSocketServer : webSocketServerSet) {
  46. sentToUser(webSocketServer.getSession(), msg);
  47. }
  48. log.info("向所有用户发送WebSocket消息完毕,消息:{}", msg);
  49. }
  50. }

3. 测试

使用Postman等工具进行WebSocket连接,连接路径为WebSocket(与前文的@ServerEndpoint内容一致)。建立连接后会收到"WebSocket is connected!"

4. 后续完善

如果你的项目中有登录功能,那么应该在你的登录时将用户的Session记录下来。你可以将Session记录在本地缓存、Redis和Grava缓存等能够建立关联关系的地方。

原文链接:https://www.cnblogs.com/jonil/p/17662742.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号