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

配置类 WebSocketConfig

@Configuration
@EnableWebSocket
public class WebSocketConfig {
    /**
     * 注入ServerEndpointExporter,
     * 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

 具体类 Websocket

@Slf4j
@Component
@ServerEndpoint("/websocket/{key}")
public class WebSocket {

    private String key;
    private Session session;

    private static final AtomicInteger onlineCount = new AtomicInteger(0);
    private static final ConcurrentHashMap<String, WebSocket> webSocketMap = new ConcurrentHashMap<>();


    @OnOpen
    public void onOpen(Session session, @PathParam(value = "key") String key) {
        this.key = key;
        this.session = session;
        if (webSocketMap.containsKey(key)) {
            log.info("【WebSocket】存在连接,已删除");
            webSocketMap.remove(key);
            webSocketMap.put(key, this);
        } else {
            webSocketMap.put(key, this);
            onlineCount.getAndIncrement();
        }
        log.info("【WebSocket】有新的连接,连接密钥为: {},当前连接数: {}", key, onlineCount);
    }


    @OnClose
    public void onClose(@PathParam("key") String key) {
        if (webSocketMap.containsKey(key)) {
            webSocketMap.remove(key);
            onlineCount.getAndDecrement();
            log.warn("【WebSocket】连接断开,断开密钥为: {},当前连接数: {}", key, onlineCount);
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.warn("【WebSocket】消息出现错误,错误密钥为: {},原因为: {}", key, error.getMessage());
        error.printStackTrace();
    }

    @OnMessage
    public void onMessage(String message, @PathParam(value = "key") String key) {
        log.info("【WebSocket】收到客户端消息: {},消息密钥为: {}", message, key);
        if (!StrUtil.isEmpty(message)) {
            JSONObject js = new JSONObject();
            js.put("key", key);
            js.put("message", message);
            log.info(js.toJSONString());
            // TODO: 2022/12/25 收到消息处理
        }
    }

    public void pushMessage(String key, String message) {
        WebSocket webSocket = webSocketMap.get(key);
        if (ObjUtil.isNotNull(webSocket)) {
            Session session = webSocket.session;
            if (ObjUtil.isNotNull(session) && session.isOpen()) {
                try {
                    log.info("【WebSocket】 发送消息: {},密钥为: {}", message, key);
                    session.getBasicRemote().sendText(message);
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }

}

前端

  • 安装vueuse  
yarn add @vueuse/core
  •  新建hook =》 useWebSocket.ts
import {unref} from 'vue';
import {useWebSocket, UseWebSocketReturn} from '@vueuse/core';

let result: UseWebSocketReturn<any>;
const listeners = new Map();

/**
 * 开启 WebSocket 链接,全局只需执行一次
 * @param url
 */
export function connectWebSocket(url: string) {
    result = useWebSocket(url, {
        // 自动重连 (遇到错误最多重复连接10次)
        autoReconnect: {
            retries: 10,
            delay: 5000
        },
    });
    if (result) {
        result.open = onOpen;
        result.close = onClose;

        const ws = unref(result.ws);
        if (ws != null) {
            ws.onerror = onError;
            ws.onmessage = onMessage;
        }
    }
}

function onOpen() {
    console.log('[WebSocket] 连接成功');
}

// @ts-ignore
function onClose(e) {
    console.log('[WebSocket] 连接断开:', e);
}

// @ts-ignore
function onError(e) {
    console.log('[WebSocket] 连接发生错误: ', e);
}

function onMessage(e: MessageEvent) {
    // console.info('[WebSocket] -----接收消息-------', e.data);
    try {
        const data = JSON.parse(e.data);
        for (const callback of listeners.keys()) {
            try {
                callback(data);
            } catch (err) {
                console.error(err);
            }
        }
    } catch (err) {
        console.error('[WebSocket] data解析失败:', err);
    }
}


/**
 * 添加 WebSocket 消息监听
 * @param callback
 */
export function onWebSocket(callback: (data: object) => any) {
    if (!listeners.has(callback)) {
        if (typeof callback === 'function') {
            listeners.set(callback, null);
        } else {
            console.debug('[WebSocket] 添加 WebSocket 消息监听失败:传入的参数不是一个方法');
        }
    }
}

/**
 * 解除 WebSocket 消息监听
 *
 * @param callback
 */
export function offWebSocket(callback: (data: object) => any) {
    listeners.delete(callback);
}

export function useMyWebSocket() {
    return result;
}
  • 在需要使用的界面引入websocket
import {connectWebSocket, onWebSocket} from "@/hooks/useWebSocket";
  • 连接初始化方法
onMounted(() => initWebSocket())
const initWebSocket = () => {
  let key = 'call'
  let url
  if (import.meta.env.VITE_BASE_API.indexOf("/lysf6") != -1) {
    url = 'ws://' + window.location.hostname + ':8081/lysf6/websocket/' + key
  } else {
    url = 'ws://' + window.location.hostname + ':4029/websocket/' + key;
  }
  connectWebSocket(url);
  console.log('【WebSocket】连接: %s', url)
  onWebSocket(onWebSocketMessage);
}
  •  收到消息方法
function onWebSocketMessage(data: any) {
  callLoading.value = false
  callData.value = data
  dataStore.setCurrentData(data)
  showDetail.value = true
}

let timer: NodeJS.Timeout | null = null;
const callLoading = ref<boolean>(false);
const callDataHandler = async () => {
  callLoading.value = true
  await getCallData(sensorStore.currentCode)
  timer = setTimeout(() => {
    callLoading.value = false
  }, 7000)
}

Logo

前往低代码交流专区

更多推荐