springBoot集成webSocket并使用postMan进行测试

发表于:2023-4-10 09:29

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:Cz范特西    来源:稀土掘金

分享:
  简单描述
  简单来讲,webSocket是一种在http协议基础上的另一种新协议,叫ws协议。
  http协议是单工通信,客户端发起请求,服务端收到请求并处理,返回给客户端,然后客户端收到服务端的请求。
  ws协议是全双工通信,客户端发起请求后,相当于搭建了一个通道,在不断开的情况下,在这期间,服务端可以把请求发给客户端,客户端也可以在这期间处理别的事情,不必等待服务端的响应。
  webSockt实现
  此次webSocket实现不包含前端代码,将使用postMan来实现前端的功能。
  依赖
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-websocket</artifactId>
          </dependency>
  配置类
  @Configuration
  public class WebSocketConfig {
      @Bean
      public ServerEndpointExporter serverEndpointExporter(){
          return new ServerEndpointExporter();
      }
  }
  webSocketServer
  package com.czf.study.wevSocket;
  import lombok.extern.slf4j.Slf4j;
  import org.junit.platform.commons.util.StringUtils;
  import org.springframework.stereotype.Component;
  import javax.websocket.*;
  import javax.websocket.server.PathParam;
  import javax.websocket.server.ServerEndpoint;
  import java.io.IOException;
  import java.util.concurrent.ConcurrentHashMap;
  /**
   * @author zfChen
   * @create 2022/11/14 15:11
   */
  @ServerEndpoint("/websocket/{userId}")
  @Component
  @Slf4j
  public class WebSocketServer {
      /**静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。*/
      private static int onlineCount = 0;
      /**concurrent包的线程安全集合,也可以map改成set,用来存放每个客户端对应的MyWebSocket对象。*/
      private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
      /**与某个客户端的连接会话,需要通过它来给客户端发送数据*/
      private Session session;
      /**接收userId*/
      private String userId="";
      /**
       * 连接建立成功调用的方法*/
      @OnOpen
      public void onOpen(Session session,@PathParam("userId") String userId) {
          this.session = session;
          this.userId=userId;
          if(!webSocketMap.containsKey(userId)){
              //加入集合中
              webSocketMap.put(userId,this);
              //在线数加1
              addOnlineCount();
          }
          log.info("用户连接:"+userId+",当前在线人数为:" + getOnlineCount());
          try {
              sendMessage("连接成功");
          } catch (IOException e) {
              log.error("用户:"+userId+",网络异常!!!!!!");
          }
      }
      /**
       * 连接关闭调用的方法
       */
      @OnClose
      public void onClose() {
          if(webSocketMap.containsKey(userId)){
              webSocketMap.remove(userId);
              //从集合中删除
              subOnlineCount();
          }
          log.info("用户退出:"+userId+",当前在线人数为:" + getOnlineCount());
      }
      /**
       * 收到客户端消息后调用的方法
       *
       * @param message 客户端发送过来的消息*/
      @OnMessage
      public void onMessage(String message, Session session) {
          log.info("【websocket消息】收到客户端发来的消息:{}", message);
      }
      /**
       *
       * @param session
       * @param error
       */
      @OnError
      public void onError(Session session, Throwable error) {
          log.error("用户错误:"+this.userId+",原因:"+error.getMessage());
          error.printStackTrace();
      }
      /**
       * 实现服务器主动推送
       */
      public void sendMessage(String message) throws IOException {
          this.session.getBasicRemote().sendText(message);
      }
      /**
       * 发送自定义消息
       * */
      public static void sendInfo(String message,@PathParam("userId") String userId) throws IOException {
          log.info("发送消息到:"+userId+",报文:"+message);
          if(StringUtils.isNotBlank(userId)&&webSocketMap.containsKey(userId)){
              webSocketMap.get(userId).sendMessage(message);
          }else{
              log.error("用户"+userId+",不在线!");
          }
      }
      public static synchronized int getOnlineCount() {
          return onlineCount;
      }
      public static synchronized void addOnlineCount() {
          WebSocketServer.onlineCount++;
      }
      public static synchronized void subOnlineCount() {
          WebSocketServer.onlineCount--;
      }
  }
  服务端发请求接口
  外面创建一个接口,模拟服务端发请求给客户端。
  @RestController
  public class DemoController {
      
      @RequestMapping("/push/{toUserId}")
      public ResponseEntity<String> pushToWeb(String message, @PathVariable String toUserId) throws IOException {
          WebSocketServer.sendInfo(message,toUserId);
          return ResponseEntity.ok("MSG SEND SUCCESS");
      }
  }
  测试
  使用postMan创建webSocket请求:
  输入webSocket的地址,1表示userId=1
  此时控制台输出
  2022-11-15 11:51:43.009  INFO 28972 --- [nio-8787-exec-5] com.czf.study.wevSocket.WebSocketServer  : 用户连接:1,当前在线人数为:1
  接下来,模拟服务端给客户端发送请求,建立一个http请求。
  控制台输出:
  2022-11-15 11:53:48.235  INFO 28972 --- [nio-8787-exec-4] com.czf.study.wevSocket.WebSocketServer  : 发送消息到:1,报文:hello
  客户端收到请求:
  双人聊天室
  webSocket经常被用作聊天室,两个客户端,通过一个服务端分发请求,进行沟通。
  在此案例中,通过/来区分,前一个是消息,后一个是发送的对象。
      /**
       * 收到客户端消息后调用的方法
       *
       * @param message 客户端发送过来的消息*/
      @OnMessage
      public void onMessage(String message, Session session) {
          log.info("【websocket消息】收到客户端发来的消息:{}", message);
          String[] split = message.split("/");
          try {
              sendInfo(split[0],split[1]);
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
  比如:
  2号用户收到1号发送的消息:
  同样的,2号也可以发送消息给1号。
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号