WebSocket 前後端示例

wxxwjef發表於2024-07-04
import cn.hutool.json.JSONUtil;
import org.springframework.stereotype.Component;

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 java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/websocket/{userId}")
@Component
public class WebSocket {
    private static ConcurrentHashMap<String, WebSocket> webSocketMap = new ConcurrentHashMap<>();
    //例項一個session,這個session是websocket的session
    private Session session;

    //新增一個方法用於主動向客戶端傳送訊息
    public static void sendMessage(Object message, String userId) {
        WebSocket webSocket = webSocketMap.get(userId);
        if (webSocket != null) {
            try {
                webSocket.session.getBasicRemote().sendText(JSONUtil.toJsonStr(message));
                System.out.println("【websocket訊息】傳送訊息成功,使用者="+userId+",訊息內容"+message.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static ConcurrentHashMap<String, WebSocket> getWebSocketMap() {
        return webSocketMap;
    }

    public static void setWebSocketMap(ConcurrentHashMap<String, WebSocket> webSocketMap) {
        WebSocket.webSocketMap = webSocketMap;
    }

    //前端請求時一個websocket時
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        this.session = session;
        webSocketMap.put(userId, this);
        sendMessage("CONNECT_SUCCESS", userId);
        System.out.println("【websocket訊息】有新的連線,連線id"+userId);
    }

    //前端關閉時一個websocket時
    @OnClose
    public void onClose(@PathParam("userId") String userId) {
        webSocketMap.remove(userId);
        System.out.println("【websocket訊息】連線斷開,總數:"+ webSocketMap.size());
    }

    //前端向後端傳送訊息
    @OnMessage
    public void onMessage(String message, @PathParam("userId") String userId) {
        if (!message.equals("ping")) {
            System.out.println("【websocket訊息】收到客戶端發來的訊息:"+message);
            sendMessage("你說的是:“" + message + "”", userId);
        }
    }
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

//開啟WebSocket的支援,並把該類注入到spring容器中
@Configuration
public class WebSocketConfig {

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

}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>本地websocket測試</title>
    <meta name="robots" content="all" />
    <meta name="keywords" content="本地,websocket,測試工具" />
    <meta name="description" content="本地,websocket,測試工具" />
    <style>
        .btn-group{
            display: inline-block;
        }
    </style>
</head>
<body>
<input type='text' value='ws://localhost:4026/websocket/1' class="form-control" style='width:390px;display:inline'
       id='wsaddr' />
<div class="btn-group" >
    <button type="button" class="btn btn-default" onclick='addsocket();'>連線</button>
    <button type="button" class="btn btn-default" onclick='closesocket();'>斷開</button>
    <button type="button" class="btn btn-default" onclick='$("#wsaddr").val("")'>清空</button>
</div>
<div class="row">
    <div id="output" style="border:1px solid #ccc;height:365px;overflow: auto;margin: 20px 0;"></div>
    <input type="text" id='message' class="form-control" style='width:810px' placeholder="待發資訊" onkeydown="en(event);">
    <span class="input-group-btn">
                <button class="btn btn-default" type="button" onclick="doSend();">傳送</button>
            </span>
</div>
</body>

<script src="jquery.min.js"></script>
<script type="text/javascript">
    function formatDate(now) {
        var year = now.getFullYear();
        var month = now.getMonth() + 1;
        var date = now.getDate();
        var hour = now.getHours();
        var minute = now.getMinutes();
        var second = now.getSeconds();
        return year + "-" + (month = month < 10 ? ("0" + month) : month) + "-" + (date = date < 10 ? ("0" + date) : date) +
            " " + (hour = hour < 10 ? ("0" + hour) : hour) + ":" + (minute = minute < 10 ? ("0" + minute) : minute) + ":" + (
                second = second < 10 ? ("0" + second) : second);
    }
    var output;
    var websocket;

    // function init() {
    //     output = document.getElementById("output");
    //     testWebSocket();
    // }

    function addsocket() {
        var wsaddr = $("#wsaddr").val();
        if (wsaddr == '') {
            alert("請填寫websocket的地址");
            return false;
        }
        StartWebSocket(wsaddr);
    }

    function closesocket() {
        websocket.close();
    }

    function StartWebSocket(wsUri) {
        websocket = new WebSocket(wsUri);
        websocket.onopen = function(evt) {
            onOpen(evt)
        };
        websocket.onclose = function(evt) {
            onClose(evt)
        };
        websocket.onmessage = function(evt) {
            onMessage(evt)
        };
        websocket.onerror = function(evt) {
            onError(evt)
        };
    }

    function onOpen(evt) {
        writeToScreen("<span style='color:red'>連線成功,現在你可以傳送資訊啦!!!</span>");
    }

    function onClose(evt) {
        writeToScreen("<span style='color:red'>websocket連線已斷開!!!</span>");
        websocket.close();
    }

    function onMessage(evt) {
        writeToScreen('<span style="color:blue">服務端回應&nbsp;' + formatDate(new Date()) + '</span><br/><span class="bubble">' +
            evt.data + '</span>');
    }

    function onError(evt) {
        console.log(evt)
        writeToScreen('<span style="color: red;">發生錯誤:</span> ' + evt.data);
    }

    function doSend() {
        var message = $("#message").val();
        if (message == '') {
            alert("請先填寫傳送資訊");
            $("#message").focus();
            return false;
        }
        if (typeof websocket === "undefined") {
            alert("websocket還沒有連線,或者連線失敗,請檢測");
            return false;
        }
        if (websocket.readyState == 3) {
            alert("websocket已經關閉,請重新連線");
            return false;
        }
        console.log(websocket);
        $("#message").val('');
        writeToScreen('<span style="color:green">你傳送的資訊&nbsp;' + formatDate(new Date()) + '</span><br/>' + message);
        websocket.send(message);
    }

    function writeToScreen(message) {
        var div = "<div class='newmessage'>" + message + "</div>";
        var d = $("#output");
        var d = d[0];
        var doScroll = d.scrollTop == d.scrollHeight - d.clientHeight;
        $("#output").append(div);
        if (doScroll) {
            d.scrollTop = d.scrollHeight - d.clientHeight;
        }
    }


    function en(event) {
        var evt = evt ? evt : (window.event ? window.event : null);
        if (evt.keyCode == 13) {
            doSend()
        }
    }
</script>

</html>

相關文章