1. 程式人生 > >Spring Boot + WebSocket Demo

Spring Boot + WebSocket Demo

最近在看 Spring Boot裡面的WebSocket  剛好以前用過socket寫過小遊戲,就動手打了Demo,期間遇到不少問題,在這裡分享下。

首先,使用websocket的話,在spring裡面可以直接使用,但是目前來說,不是所有瀏覽器和伺服器都支援websocket,考慮實際需求的話,還是要加上sock.js,這樣才能保證實現的產品穩定性。

直接實現的話,這篇文章 寫的不錯,程式碼我跑過可以執行,這裡按下不表。

使用socket.js的話,有會幾個坑。先上書上程式碼:

第一步當然是建立Spring Boot Project

第二步,在pom檔案加入WebSocket的依賴

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

第三步,編寫Handler類

@Component
public class MarcoHandler extends AbstractWebSocketHandler {

    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {

        Thread.sleep(2000);

        System.out.println(message.toString());

        session.sendMessage(new TextMessage("Polo!"));


    }

}
這個類拓展了 AbstractWebSocketHandler 這個類,主要是實現 WebocketHandler 這個介面,從而使用Spring的底層級WebSocet API來處理訊息文字。handleTextMessage 是 AbstractWebSocketHandler 其中的一個方法,重寫該方法處理文字型別的訊息。

有了處理訊息的方法,接下來,就是把訊息匯入到這裡,那麼剩下的工作就簡單了,接受瀏覽器的請求,並分配到這個方法來。為此,我們需要一個配置類。

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Autowired
    MarcoHandler marcoHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
        //webSocketHandlerRegistry.addHandler(marcoHandler,"/marco").setAllowedOrigins("*").withSockJS();
        webSocketHandlerRegistry.addHandler(marcoHandler,"/marco").setAllowedOrigins("http://localhost:63342").withSockJS();
    }

}
首先必須把上一把寫好的處理訊息類當成bean依賴進來,然後實現WebSocketConfigurer介面重寫裡面的註冊方法註冊一個端點,裡面這個端點來接收來自“/marco” 的請求,然後把它分配給我們上一步建立好的bean,簡單明瞭吧~

第三步,瀏覽器端

var url = "http://localhost:8090/marco";

var sock = new SockJS(url);

sock.onopen = function(){
   console.log("opening");
   sayMarco();
};

sock.onmessage = function(e){
   console.log("Receive message: " , e.data);
   setTimeout(function(){sayMarco()},2000);
};

sock.onclose = function(){
   console.log("Closing");
};

function sayMarco(){
   console.log("Sending marco!");
   sock.send("Marco");
}

首先,因為是 sock.js 的原因,所以url 是 http或者https,而不能使 ws

其次,生成 sockjs 物件,然後重寫裡面的onopen,onmessage,onclose 等方法就可以了 

OK,程式碼總算搬完了,坑在哪裡呢

1、 無論我之前怎麼改 url 都是報 404 NOT FOUND 錯誤

後來發現我的配置類沒有加 @Config 註解,導致註冊的端點沒註冊上,所以才報404

2、加上 註解之後 改成報 403 錯誤

後來牆了一下,發現是 跨域問題,因為Spring為了保護應用,幫我們加了攔截器防止跨域,所以我們可以在配置類使用 setAllowedOrigins("*")

這個方法允許我們跨域訪問,但是 spring官方 推薦的方式是這樣的 

.setAllowedOrigins("http://mydomain.com")

這個看具體應用了吧