websocket在springboot+vue中的使用教程

 更新时间:2019年08月17日 10:27:49   作者:会飞的joy  
这篇文章主要介绍了websocket在springboot+vue中的使用教程,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

1、websocket在springboot中的一种实现

  在java后台中,websocket是作为一种服务端配置,其配置如下

@Configuration
public class WebSocketConfig {
  
  @Bean(name="serverEndpointExporter")
  public ServerEndpointExporter getServerEndpointExporterBean(){
    return new ServerEndpointExporter();
  }
}

  加入上面的配置之后就可以编辑自己的websocket实现类了,如下

@Component
@ServerEndpoint(value = "/messageSocket/{userId}")
public class MessageWebSocket {
  private static final Logger logger = LoggerFactory.getLogger(MessageWebSocket.class);
  /**
   * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
   */
  private static int onlineCount = 0;
  /**
   * key: userId value: sessionIds
   */
  private static ConcurrentHashMap<Integer, ConcurrentLinkedQueue<String>> userSessionMap = new ConcurrentHashMap<>();
  /**
   * concurrent包的线程安全Map,用来存放每个客户端对应的MyWebSocket对象。
   */
  private static ConcurrentHashMap<String, MessageWebSocket> websocketMap = new ConcurrentHashMap<>();
  /**
   * key: sessionId value: userId
   */
  private static ConcurrentHashMap<String, Integer> sessionUserMap = new ConcurrentHashMap<>();
  /**
   * 当前连接会话,需要通过它来给客户端发送数据
   */
  private Session session;
  /**
   * 连接建立成功调用的方法
   * */
  @OnOpen
  public void onOpen(Session session, @PathParam("userId") Integer userId) {
    System.out.println(applicationContext);
    try {
      this.session = session;
      String sessionId = session.getId();
      //建立userId和sessionId的关系
      if(userSessionMap.containsKey(userId)) {
        userSessionMap.get(userId).add(sessionId);
      }else{
        ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
        queue.add(sessionId);
        userSessionMap.put(userId, queue);
      }
      sessionUserMap.put(sessionId, userId);
      //建立sessionId和websocket引用的关系
      if(!websocketMap.containsKey(sessionId)){
        websocketMap.put(sessionId, this);
        addOnlineCount();      //在线数加1
      }
    }catch (Exception e){
      logger.error("连接失败");
      String es = ExceptionUtils.getFullStackTrace(e);
      logger.error(es);
    }
  }
  /**
   * 连接关闭调用的方法
   */
  @OnClose
  public void onClose() {
    String sessionId = this.session.getId();
    //移除userId和sessionId的关系
    Integer userId = sessionUserMap.get(sessionId);
    sessionUserMap.remove(sessionId);
    if(userId != null) {
      ConcurrentLinkedQueue<String> sessionIds = userSessionMap.get(userId);
      if(sessionIds != null) {
        sessionIds.remove(sessionId);
        if (sessionIds.size() == 0) {
          userSessionMap.remove(userId);
        }
      }
    }
    //移除sessionId和websocket的关系
    if (websocketMap.containsKey(sessionId)) {
      websocketMap.remove(sessionId);
      subOnlineCount();      //在线数减1
    }
  }
  /**
   * 收到客户端消息后调用的方法
   *
   * @param messageStr 客户端发送过来的消息
   **/
  @OnMessage
  public void onMessage(String messageStr, Session session, @PathParam("userId") Integer userId) throws IOException {
  }
  /**
   *
   * @param session
   * @param error 当连接发生错误时的回调
   */
  @OnError
  public void onError(Session session, Throwable error) {
    String es = ExceptionUtils.getFullStackTrace(error);
    logger.error(es);
  }
  /**
   * 实现服务器主动推送
   */
  public void sendMessage(String message, Integer toUserId) throws IOException {
    if(toUserId != null && !StringUtil.isEmpty(message.trim())){
      ConcurrentLinkedQueue<String> sessionIds = userSessionMap.get(toUserId);
      if(sessionIds != null) {
        for (String sessionId : sessionIds) {
          MessageWebSocket socket = websocketMap.get(sessionId);
          socket.session.getBasicRemote().sendText(message);
        }
      }
    }else{
      logger.error("未找到接收用户连接,该用户未连接或已断开");
    }
  }
  public void sendMessage(String message, Session session) throws IOException {
    session.getBasicRemote().sendText(message);
  }
   /**
  *获取在线人数
  */
  public static synchronized int getOnlineCount() {
    return onlineCount;
  }
   /**
  *在线人数加一
  */
  public static synchronized void addOnlineCount() {
    MessageWebSocket.onlineCount++;
  }
  /**
  *在线人数减一
  */
  public static synchronized void subOnlineCount() {
    MessageWebSocket.onlineCount--;
  }
}

到此后台服务端的工作已经做好了,前端如何作为客户端进行连接呢,请继续往下看。。

为了实现断开自动重连,我们使用的reconnecting-websocket.js组件

//websocket连接实例
let websocket = null;
//初始话websocket实例
function initWebSocket(userId) {
  // ws地址 -->这里是你的请求路径
  let host = urlConfig.wsUrl + 'messageSocket/' + userId;
  if ('WebSocket' in window) {
    websocket = new ReconnectingWebSocket(host);
    // 连接错误
    websocket.onerror = function () {
    }
    // 连接成功
    websocket.onopen = function () {
    }
    // 收到消息的回调,e.data为收到的信息
    websocket.onmessage = function (e) {
    }
    // 连接关闭的回调
    websocket.onclose = function () {
    }
    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
      closeWebSocket();
    }
  } else {
    alert('当前浏览器不支持websocket')
    return;
  }
}
//关闭WebSocket连接
function closeWebSocket() {
  websocket.close();
}
//发送消息
function sendMessage(message){
  websocket.send(message);
}

至此一个简易的完整的websocket已经完成了,具体功能可以依此为基本进行扩展。

总结

以上所述是小编给大家介绍的websocket在springboot+vue中的使用教程,希望对大家有所帮助,如果大家有任何疑问欢迎给大家留言,小编会及时回复大家的!

相关文章

  • springBoot集成mybatis 转换为 mybatis-plus方式

    springBoot集成mybatis 转换为 mybatis-plus方式

    这篇文章主要介绍了springBoot集成mybatis 转换为 mybatis-plus方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • SpringBoot自动装配的原理与使用

    SpringBoot自动装配的原理与使用

    在现代的软件开发中,依赖管理是一个关键的任务,随着应用程序规模的增长,手动管理对象之间的依赖关系变得越来越复杂,为了解决这个问题,Spring Boot提供了一种强大的功能,即自动装配,感兴趣想要详细了解可以参考下文
    2023-05-05
  • SpringBoot加载读取配置文件过程详细分析

    SpringBoot加载读取配置文件过程详细分析

    在实际的项目开发过程中,我们经常需要将某些变量从代码里面抽离出来,放在配置文件里面,以便更加统一、灵活的管理服务配置信息。所以本文将为大家总结一下SpringBoot加载配置文件的常用方式,需要的可以参考一下
    2023-01-01
  • Spring Boot中RedisTemplate的使用示例详解

    Spring Boot中RedisTemplate的使用示例详解

    RedisTemplate.opsForHash()是RedisTemplate类提供的用于操作Hash类型的方法,它可以用于对Redis中的Hash数据结构进行各种操作,如设置字段值、获取字段值、删除字段值等,本文介绍Spring Boot中RedisTemplate的使用,感兴趣的朋友一起看看吧
    2023-10-10
  • 解析JavaSe的抽象类和接口

    解析JavaSe的抽象类和接口

    这篇文章主要为大家详细介绍了JavaSe的抽象类和接口,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • mybatis之嵌套查询和嵌套结果有哪些区别

    mybatis之嵌套查询和嵌套结果有哪些区别

    这篇文章主要介绍了mybatis之嵌套查询和嵌套结果有哪些区别,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Java项目导入IDEA的流程配置以及常见问题解决方法

    Java项目导入IDEA的流程配置以及常见问题解决方法

    通常一个团队中可能有人用eclipse,有人用intelliJ,那么经常会出现需要导入别人用eclipse建好的web项目,下面这篇文章主要给大家介绍了关于Java项目导入IDEA的流程配置以及常见问题解决方法的相关资料,需要的朋友可以参考下
    2023-05-05
  • Spring Cache监控配置与使用规范的建议

    Spring Cache监控配置与使用规范的建议

    这篇文章主要介绍了Spring Cache监控配置与使用规范的建议,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • java使用短信设备发送sms短信的示例(java发送短信)

    java使用短信设备发送sms短信的示例(java发送短信)

    这篇文章主要介绍了java使用短信设备发送sms短信的示例(java发送短信),需要的朋友可以参考下
    2014-04-04
  • SpringBoot SpringSecurity JWT实现系统安全策略详解

    SpringBoot SpringSecurity JWT实现系统安全策略详解

    Spring Security是Spring的一个核心项目,它是一个功能强大且高度可定制的认证和访问控制框架。它提供了认证和授权功能以及抵御常见的攻击,它已经成为保护基于spring的应用程序的事实标准
    2022-11-11

最新评论