Spring WebSocket踩坑指南


Spring WebSocket踩坑指南

本次公司項目中需要在后台與安卓App間建立一個長連接,這里采用了Spring的WebSocket,協議為Stomp。
關於Stomp協議這里就不多介紹了,網上一搜一大把,這里主要說下在配置過程的踩過的那些坑。

官網才是首選

首先在我們第一次嘗試WebSocket肯定會搜尋各種各樣的博客,在看完關於Stomp和長連接的基礎知識,確定使用Spring WebSocket后,請馬上進入官網Spring WebSocket,並下載該網站右側的源碼,這將節省大量時間。網上的各個博客都是對官網的一定翻譯而已,重復性的內容過多,直接閱讀官網就好。接下來就是一步步排雷組裝到自己的項目中了。
正因為官網的存在,本篇文章只講踩坑,配置步驟詳見官網文檔與源碼。

依賴

    <!-- stomp協議websocket長連接 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-websocket</artifactId>
        <!-- 該部分的版本號一般與當前項目的Spring版本號一致即可 -->
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-messaging</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- 長連接中消息的傳遞使用JSON格式,
    該依賴幫助Spring自動在Object與JSON之間轉換,
    不加的話會在傳遞消息時報錯-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.5.3</version>
    </dependency>
    <dependency>
      <groupId>javax.websocket</groupId>
      <artifactId>javax.websocket-api</artifactId>
      <version>1.1</version>
      <scope>provided</scope>
    </dependency>

spring掃描問題

在項目配置過程中,我出現了客戶端無法向服務器發送請求的錯誤。事實上服務器已經收到了請求,此時打印日志:
No matching message handler methods.
此時我們的目標是客戶端向服務器的指定接口發送數據,日志的意思為服務器已經接收到消息但沒有合適的方法去處理它。這是因為在所需處理的方法上的注解@Message並沒有被Spring MVC掃描到。在Spring Boot中不會出現這個問題,但在Spring MVC中可以查看配置文件spring-mvc.xml中在組件掃描中是否加入了use-default-filters="false"。use-default-filters="true"為默認配置,即允許Spring掃描配置包下的所有組件;而設為false后僅允許Spring控制網站的跳轉邏輯,忽略了@Message注解。刪除即可。

web.xml 3.0

Java Async support must be enabled on a servlet and for all filters involved in async request processing. This is done in Java code using the Servlet API or by adding "<async-supported>true</async-supported>" to servlet and filter declarations in web.xml. Also you must use a Servlet 3.0+ container

報錯很清晰了,請將web.xml從2.0修改為3.0,並在filter中加入配置<async-supported>true</async-supported>,作用是支持異步處理。

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

302

這是在使用SockJS時出現的問題。這是因為我們項目中使用了Shiro作為權限管理,將所需暴露的接口配置一下即可。

https - wss 403

如果我們網站正式服務器采用了https協議,那么相對應的WebSocket的協議必須為wss。否則出現403問題。解決的另一種情況可以參見Nginx反向代理WebSocket響應403的解決辦法,不過我沒有使用它,也沒有測過。

handshake: Unexpected response code: 400

這是由於正式服務器中采用了NGINX作為反向代理,這里需要更新下NGINX配置,具體如下:

    location /{
        proxy_pass        http://wsbackend;
        // 解決下面60s自動斷開的問題
        proxy_read_timeout          600s;
        # WebSocket support (nginx 1.4),加入以下幾行
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        }

}

WebSocket 60s自動斷開連接

還是NGINX問題。解決方案已經在上面指出。proxy_read_timeout 默認為60s,如果NGINX對一個長連接在讀取一次數據60s后沒有再次接收到消息,則認為已超時,並關閉該連接,所以前端很准時的60s后開始報錯。這里將時間修改到了10分鍾,可以根據自己情況調整。

心跳

繼續上面的話題,即使修改了超時時間為10分鍾也沒有實質性的改變,這時候心跳包就需要登場了。心跳包設計可以參考一種心跳,兩種設計| 徐靖峰|個人博客高效保活長連接:手把手教你實現 自適應的心跳保活機制這兩篇博客。第二篇博客更多關於安卓端。

安卓端SDK

這里我在GitHub上找了一個包:

'com.github.forresthopkinsa:StompProtocolAndroid:17.09.1'
```;
具體見[GitHub](https://github.com/NaikSoftware/StompProtocolAndroid)。

## 安卓端進程防殺死補充

這部分可以參考[FV懸浮球的說明](https://www.kancloud.cn/sealt/fooview/382748)。同時也推薦下這款軟件,在安卓上的手勢輔助功能很好用。

End.


免責聲明!

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



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