2

引言

学完了协议基础,我们一起使用spring-boot搭建一个websocket项目。

WebSocket 实现

以下的代码实现十分简单,建立起WebSocket连接后,后台向前台推送一些数据,前台回复收到。

后台

如下所示,后台编写一个Handler,实现WebSocketHandler拥有处理WebSocket的能力,实现方法。

@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实现。

建立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与用户之间的对应关系。

image.png

用户认证可以使用token来实现。

认证

之前我们讲过,WebSocket的建立需要先发送HTTP请求进行握手,我们可以在握手中鉴别用户身份。

握手拦截器,此处是获取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)事件(小声,据说查得挺严的),让我庆幸挂在三面。同时,我也似乎感悟更深。

别拘泥框架,技术不止框架。别迷恋技术,人生远比这广。


张喜硕
2.1k 声望423 粉丝

浅梦辄止,书墨未浓。