【SpringBoot 】 注解之WebSocket初體驗


之前用.net的一個開源框架寫了WebSocket的應用,剛好pmgo有用到。現如今需要自己做一個簡易聊天室,前端也寫了一些,服務端打算用Java(.netcore擼了一天,都沒看出個所以然來,連WebSocket的端口都不知道怎么設置ಥ_ಥ,雖然下面這個Demo也沒有找到如何設置。)下面就動手實操吧

一、pom.xml引入包

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

在依賴中添加如上代碼段,引入websocket包。

二、WebSocketUtil

接下來創建一個WebSocketUtil類,用於提供對session鏈接、斷開連接、推送消息的簡單控制。

(注:此處的sendMessage,直接將字符串消息推送給客戶端。現下先后端分離的應用,都采用Json數據傳輸標准,所以后期最好將其封裝為標准的Json對象)

public class WebsocketUtil {
    /**
     * 記錄當前在線的Session
     */
    private static final Map<String, Session> ONLINE_SESSION = new ConcurrentHashMap<> ();

    /**
     * 添加session
     * @param userId
     * @param session
     */
    public static void addSession(String userId, Session session){
        // 此處只允許一個用戶的session鏈接。一個用戶的多個連接,我們視為無效。
        ONLINE_SESSION.putIfAbsent ( userId, session );
    }

    /**
     * 關閉session
     * @param userId
     */
    public static void removeSession(String userId){
        ONLINE_SESSION.remove ( userId );
    }

    /**
     * 給單個用戶推送消息
     * @param session
     * @param message
     */
    public static void sendMessage(Session session, String message){
        if(session == null){
            return;
        }

        // 同步
        RemoteEndpoint.Async async  = session.getAsyncRemote ();
        async.sendText ( message );
    }

    /**
     * 向所有在線人發送消息
     * @param message
     */
    public static void sendMessageForAll(String message) {
        //jdk8 新方法
        ONLINE_SESSION.forEach((sessionId, session) -> sendMessage(session, message));
    }
}

三、WebSocketController

如上,已經創建好了簡單的session管理和消息管理,接下來要使用注解的方式,使用SpringBoot的websocket包提供的方法,實現OnOpen、OnClose、OnMessage三個方法,再實現一個OnError方法來應對異常。代碼段如下:

/**
 * websocket接口處理類
 */
@Component
@ServerEndpoint ( value = "/chat/{userid}" )
public class WebsocketController {

    /**
     * 連接事件,加入注解
     * @param userId
     * @param session
     */
    @OnOpen
    public void onOpen( @PathParam  ( value = "userid" ) String userId, Session session ) {
        String message ="[" + userId + "]加入聊天室!!";

        // 添加到session的映射關系中
        WebsocketUtil.addSession ( userId, session );
        // 廣播通知,某用戶上線了
        WebsocketUtil.sendMessageForAll ( message );
    }

    /**
     * 連接事件,加入注解
     * 用戶斷開鏈接
     * @param userId
     * @param session
     */
    @OnClose
    public void onClose(@PathParam  ( value = "userId" ) String userId, Session session ) {
        String message ="[" + userId + "]退出了聊天室...";

        // 刪除映射關系
        WebsocketUtil.removeSession ( userId );
        // 廣播通知,用戶下線了
        WebsocketUtil.sendMessageForAll ( message );
    }

    /**
     * 當接收到用戶上傳的消息
     * @param userId
     * @param session
     */
    @OnMessage
    public void onMessage(@PathParam  ( value = "userId" ) String userId, Session session ,String message) {
        String msg ="[" + userId + "]:"+message;

        // 直接廣播
        WebsocketUtil.sendMessageForAll ( msg );
    }

    /**
     * 處理用戶活連接異常
     * @param session
     * @param throwable
     */
    @OnError
    public void onError(Session session, Throwable throwable) {
        try {
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        throwable.printStackTrace();
    }
}

到此基本完成了websocket的服務。

四、添加 ServerEndpointExporter 啟動Bean

修改main函數所在的啟動方法代碼段,添加 serverEndpointExporter :

public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    /**
     * 會自動注冊使用了@ServerEndpoint注解聲明的Websocket endpoint
     * 要注意,如果使用獨立的servlet容器,
     * 而不是直接使用springboot的內置容器,
     * 就不要注入ServerEndpointExporter,因為它將由容器自己提供和管理。
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

至此,完成了所有代碼的編寫。

 

五、測試

使用 http://coolaf.com/tool/chattest 這個站點,來測試鏈接。首先啟動項目,啟動后,點開網址輸入應用的WebSocket鏈接url:ws://127.0.0.1:5088/chat/user1 測試鏈接

 

參考文章:https://www.imooc.com/article/68964

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM