springbootwebsocket

spring websocket簡單實踐

Spring提供的類和接口

spring 定義了一些接口和抽象類,我們只要實現這些接口和抽象類,就能夠完成一個目錄比較清晰的 WebSocket的服務器端,並且它裏面有很多封裝的功能,我們可以直接使用

  1. HttpSessionHandshakeInterceptor(抽象類):握手攔截器,在握手前後添加操作
  2. AbstractWebSocketHandler(抽象類):WebSocket處理程序,監聽連接前,連接中,連接後
  3. WebSocketConfigurer(接口):配置程序,比如配置監聽那個端口,上面的握手攔截器,處理程序的使用

消息和身份對象

package com.ruoyi.websocket.spring;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.web.socket.WebSocketSession;
@AllArgsConstructor
@Data
public class SessionBean {
    private WebSocketSession webSocketSession;
    private  Integer cleintId;

}

攔截器

package com.ruoyi.websocket.spring;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import java.util.Map;

@Component
@Slf4j
public class MyWsInterceptor extends HttpSessionHandshakeInterceptor {
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        log.info(request.getRemoteAddress().toString()+"開始握手了");
        return super.beforeHandshake(request, response, wsHandler, attributes);
    }
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
        log.info(request.getRemoteAddress().toString()+"完成握手了");
        super.afterHandshake(request, response, wsHandler, ex);
    }
}

處理器

package com.ruoyi.websocket.spring;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 處理程序
 */
@Component
@Slf4j
public class MyWsHandler extends AbstractWebSocketHandler {
    private static Map<String,SessionBean> sessionBeanMap;
    private static AtomicInteger cleintIdMaker;
    static {
        sessionBeanMap=new ConcurrentHashMap<>();
        cleintIdMaker=new AtomicInteger(0);
    }

    //連接連接後
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);
        SessionBean sessionBean=new SessionBean(session,cleintIdMaker.getAndIncrement());
        sessionBeanMap.put(session.getId(),sessionBean);
        log.info(sessionBeanMap.get(session.getId()).getCleintId()+":連接打開");
    }

    //收到消息的處理
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        super.handleTextMessage(session, message);
        log.info(sessionBeanMap.get(session.getId()).getCleintId()+":"+message.getPayload());
    }

    //傳輸異常
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        super.handleTransportError(session, exception);
        if(session.isOpen()){
            session.close();
        }
        sessionBeanMap.remove(session.getId());

    }
    //連接關閉

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
        log.info(sessionBeanMap.get(session.getId()).getCleintId()+":連接關閉");
    }

    //每2秒向客戶端發送消息
    @Scheduled(fixedRate = 2000)
    public  void sendMsg() throws IOException {
        for (String key:sessionBeanMap.keySet()){
            sessionBeanMap.get(key).getWebSocketSession().sendMessage( new TextMessage("心跳測試"));
        }
        log.info("websocket send message");

    }
}

配置類

package com.ruoyi.websocket.spring;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

import javax.annotation.Resource;

@Configuration
@EnableWebSocket
public class MyWsConfig implements WebSocketConfigurer {
    @Resource
    MyWsHandler myWsHandler;
    @Resource
    MyWsInterceptor myWsInterceptor;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {

        registry.addHandler(myWsHandler,"/myWs")
                        .addInterceptors(myWsInterceptor)
                        .setAllowedOrigins("*");
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章