WebSocket 之應用實現

引言

學完了協議基礎,咱們一塊兒使用spring-boot搭建一個websocket項目。javascript

WebSocket 實現

如下的代碼實現十分簡單,創建起WebSocket鏈接後,後臺向前臺推送一些數據,前臺回覆收到。java

後臺

以下所示,後臺編寫一個Handler,實現WebSocketHandler擁有處理WebSocket的能力,實現方法。web

@Component
public class YunzhiWebSocketHandler implements WebSocketHandler {

    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        System.out.println("創建鏈接");
        webSocketSession.sendMessage(new TextMessage("Hello!"));
        webSocketSession.sendMessage(new TextMessage("This is yunzhiclub."));
        webSocketSession.sendMessage(new TextMessage("I am yunzhi's server."));
        webSocketSession.sendMessage(new TextMessage("I am sending message."));
    }

    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
        System.out.println("收到數據" + webSocketMessage.getPayload().toString());
    }

    @Override
    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
        System.out.println("發生錯誤");
    }

    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
        System.out.println("鏈接關閉");
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}

前臺

前臺不引入任何JavaScript第三方庫,直接使用原生WebSocket API實現。spring

創建WebSocket鏈接。websocket

var websocket = new WebSocket('ws://127.0.0.1:8080/websocket');

websocket.onpen = function(event) {
    console.log('創建WebSocket鏈接');
};

websocket.onclose = function(event) {
    console.log('關閉WebSocket鏈接');
};

websocket.onmessage = function(event) {
    console.log('收到消息', event.data);
    websocket.send('收到!');
};

websocket.onerror = function() {
    console.log('WebSocket發生錯誤');
};

window.onbeforeunload = function() {
    websocket.close();
};

路由配置

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    private final YunzhiWebSocketHandler handler;

    public WebSocketConfig(YunzhiWebSocketHandler handler) {
        this.handler = handler;
    }

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(handler, "websocket").setAllowedOrigins("*");
    }
}

效果

在網絡中,便可查看WebSocket的數據收發狀況。網絡

image.png

不足分析

寫完WebSocket代碼以後,忽然以爲本身以前舉的在線聊天的栗子很差實現。單一用戶的推送,使用WebSocket很困難。框架

推送的時候,須要使用WebSocketSession進行推送,因此就須要驗證WebSocketSession與用戶之間的對應關係。socket

image.png

用戶認證可使用token來實現。ide

認證

以前咱們講過,WebSocket的創建須要先發送HTTP請求進行握手,咱們能夠在握手中鑑別用戶身份。spring-boot

握手攔截器,此處是獲取token的示例,就像普通的HTTP同樣。

@Component
public class WebSocketInterceptor implements HandshakeInterceptor {

    @Override
    public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
        if (serverHttpRequest instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest request = (ServletServerHttpRequest) serverHttpRequest;
            String token = request.getServletRequest().getParameter("token");
            System.out.println(token);
        }
        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {

    }
}

配置攔截器:

private final WebSocketInterceptor interceptor;

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    registry.addHandler(handler, "websocket").addInterceptors(interceptor).setAllowedOrigins("*");
}

前臺在創建鏈接的時候添加token認證信息:

var websocket = new WebSocket('ws://127.0.0.1:8080/websocket?token=23147823975891374859435');

在握手的時候,後臺便可獲取token信息,獲悉用戶身份。

image.png

總結

最近的感受就是語言和框架的重要性逐漸下降,我再也不喜歡去看什麼《Spring Boot核心思想》、《Spring Cloud微服務實戰》這些書,學完真的感受沒什麼用,沒人敢保證一項技術長青。

如今,我開始學習IO模型、學習Linux

字節跳動的消(cu)極(si)事件(小聲,聽說查得挺嚴的),讓我慶幸掛在三面。同時,我也彷佛感悟更深。

別拘泥框架,技術不止框架。別迷戀技術,人生遠比這廣。

相關文章
相關標籤/搜索