当前位置: 首页 > article >正文

SpringBoot + Vue实现websocket

后端代码

pom.xml增加依赖

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

增加ServerEndpointExporter Bean

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * @Author zhangyugu
 * @Date 2022/3/28 5:00 下午
 * @Version 1.0
 */
@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

增加websocket事件的监听器和发送消息工具类 WebSocketHandler,增加该类后SpringBoot服务接收到形如 /ws/xxx 的url请求将进入如下代码逻辑。

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@ServerEndpoint(value = "/ws/{token}")
@Component
public class WebSocketHandler {
	
	static Map<String, Session> sessions = new HashMap<>();

    /**
	 * 打开连接
	 * @param session
	 * @param token 当前登录用户的token,用于标识该连接的用户
	 */
	@OnOpen
	public void open(Session session, @PathParam("token") String token) {
		if(StringUtils.isBlank(token)) {
			return;
		}
		sessions.put(token, session);
	}
	
	/**
	 * 关闭连接
	 * @param session
	 */
	@OnClose
	public void close(Session session) {
		Iterator<Map.Entry<String, Session>> itr = sessions.entrySet().iterator();
		while(itr.hasNext()) {
			Map.Entry<String, Session> entry = itr.next();
			if(entry.getValue().equals(session)) {
				itr.remove();
			}
		}
	}
	
	/**
	 * 收到消息
	 * @param session
	 * @param msg
	 */
	@OnMessage
	public void onMessage(Session session, String msg) {
		log.debug("getMsg from {}:{}", session.getId(), msg);
	}
	
	/**
	 * 发送消息的方法
	 * @param token
	 * @param msg
	 * @throws IOException
	 */
	public static void sendMsg(String token, String msg) throws IOException {
		Session session = sessions.get(token);
		if(session!=null) {
			session.getBasicRemote().sendText(msg);
		}
	}
}

前端代码

<template>
  <div>
    <input type="text" v-model="inputMessage">
    <button @click="sendMessage">发送</button>
    <div>接收到消息:<br>
        {{receivedMsg}}
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      socket: null,
      receivedMsg: '',
      inputMessage: ''
    };
  },
  mounted() {
    // Create a new WebSocket connection
    let baseUrl = "localhost:2222";
    let token = "xx";//登录得到的token
    this.socket = new WebSocket(`ws://${baseUrl}/ws/${token}`);
    
    // Set up event listeners
    this.socket.onopen = (event) => {
      console.log('WebSocket connection opened.');
    };
    
    this.socket.onmessage = (event) => {
      this.receivedMsg += event.data;
    };
    
    this.socket.onerror = (error) => {
      console.error('WebSocket Error:', error);
    };
    
    this.socket.onclose = (event) => {
      console.log('WebSocket connection closed.');
    };
    
    // 定时检查连接是否正常,不正常则重连
    this.timer = setInterval(() => {
			if (this.socket) {
				if (this.socket.readyState == 1) {
					try {
						this.socket.send('heartbeat');
						console.log('heartbeat');
					} catch (err){
						console.log('断线:' + err);
						this.connect();
					}
				} else if(this.socket.readyState == 3) {
					console.log('reconnect');
					this.connect();
				}
			}
		}, 10000);
     
  },
  methods: {
    connect() {
        // Create a new WebSocket connection
        let baseUrl = "localhost:2222";
        let token = "xx";//登录得到的token
        this.socket = new WebSocket(`ws://${baseUrl}/ws/${token}`);
    },
    sendMessage() {
      if (this.socket && this.inputMessage) {
        this.socket.send(this.inputMessage);
        this.inputMessage = ''; // Clear the input field after sending
      }
    }
  },
  beforeDestroy() {
     // Close the WebSocket connection when the component is destroyed
     if (this.socket) {
       this.socket.close();
     }
     if (this.timer) {
        clearInterval(this.timer);
     }
   }
};
</script>


http://www.kler.cn/a/285962.html

相关文章:

  • <Rust>egui学习之小部件(四):如何在窗口中添加滚动条Scroll部件?
  • 浅析Java线程池实现原理
  • Facebook广告投放转化API对接开发讲解
  • C++编辑器安装
  • CSAPP Data Lab
  • C++_CH09_循环
  • 网络层 IV(ARP、DHCP、ICMP)【★★★★★★】
  • Linux文件操作(二)
  • C++/Qt 多媒体(续四)
  • select epoll搭建并发式服务器
  • 强化学习——马尔可夫决策过程的理解
  • 【扩散模型(六)】IP-Adapter 是如何训练的?2 源码篇(IP-Adapter Plus)
  • 使用PostgreSQL的CLI客户端查询数据不显示问题
  • 计算机网络概述(协议层次与服务模型)
  • 爬虫引流推广使用IP
  • 公务员面试(c语言)
  • 【网络基础】探讨以太网:封装解包、MTU、MAC地址与碰撞
  • XR虚拟拍摄短剧 | 探索虚拟制作在短剧领域的应用与发展
  • 若依微服务ruoyi-auth在knife4j中不显示问题解决
  • .net dataexcel winform控件 更新 日志