SpringBoot如何使用WebSocket實現前后端交互?


背景

我們都知道http協議只能在瀏覽器單方面向服務器發起請求時獲得響應,然而服務器不能主動向瀏覽器推送消息,想要實現瀏覽器的主動推送目前有兩種主流的實現方式:

  • 輪詢:缺點很多,但是實現簡單
  • websocket: 在瀏覽器和服務器之間建立TCP連接,實現全雙工通信
    springboot使用websocket有兩種方式,一種是實現簡單的websocket,另外一種是實現STOMP協議。本篇講述如何使用springboot實現簡單的websocket。

實現

一、導入依賴

直接在pom.xml中導入依賴。

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

二、新建WebSocket配置類,注入Bean

首先注入一個ServerEndpointExporterBean,該Bean會自動注冊使用@ServerEndpoint注解申請的websocket endpoint,代碼如下:

@Component
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

三、新建WebSocket服務端,在其中處理websocket邏輯

@Component  //注冊到容器中
@ServerEndpoint("/webSocket")  //接收websocket請求路徑
@Slf4j
public class WebSocket {
    //當前連接(每個websocket連入都會創建一個WebSocket實例)
    private Session session;

    //定義一個websocket容器存儲session,即存放所有在線的socket連接
    private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<>();

    //處理連接建立
    @OnOpen
    public void opOpen(Session session){
        this.session = session;
        log.info("【有新的客戶端連接了】:{}",session.getId());
        webSocketSet.add(this);  //將新用戶加入在線組
        log.info("【websocket消息】有新的連接,總數:{}",webSocketSet.size());
    }

    //處理連接關閉
    @OnClose
    public void Onclose(){
        webSocketSet.remove(this);
        log.info("【websocket消息】連接斷開,總數:{}",webSocketSet.size());
    }

    //接受消息
    @OnMessage
    public void onMessage(String message){
        log.info("【websocket消息】收到客戶端發來的消息:{}",message);
    }

    // 群發消息
    public void sendMessage(String message) {
        for (WebSocket webSocket : webSocketSet) {
            log.info("【websocket消息】廣播群發消息,message={}",message);
            try {
                webSocket.session.getBasicRemote().sendText(message);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

四、客戶端實現,可以借助FreeMarker模板工具直接寫在ftl文件里。

由於部分瀏覽器可能不支持,可以先測試,代碼如下:

<script>
    var websocket = null;
    if('WebSocket' in window){
        websocket = new WebSocket('ws://localhost:8080/webSocket');
    }else{
        alert('當前瀏覽器不支持websocket消息通知');
    }

    //連接成功建立的回調方法
    websocket.onopen = function (event) {
        console.log("ws建立連接成功");
    }

    //連接關閉的回調方法
    websocket.onclose = function (event) {
        console.log("ws連接關閉");
    }

    //接收到消息的回調方法
    websocket.onmessage = function (event) {
        /*setMessageInnerHTML(event.data);*/
       // alert("ws接收返回消息:"+event.data);
        console.log("服務器返回消息: " + event.data);
        //彈窗提醒(要用到JQuary,所以要先引入JQuary)   播放音樂
        $('#mymodal').modal('show')
    }

    //連接發生錯誤的回調方法
    websocket.onerror = function(event){
        alert('websocket通信發生錯誤!')
    }

    //監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。
    window.onbeforeunload = function() {
        websocket.close();
    }
    </script>

五、測試(項目實現客戶創建新訂單之后,前台發出提醒)

@Autowired
private WebSocket webSocket;

@Override
    @Transactional
    public OrderDTO create(OrderDTO orderDTO) {//創建訂單
        。。。。(具體代碼省略)

       //創建新訂單  發送websocket消息
        webSocket.sendMessage(orderDTO.getOrderId());
        return orderDTO;
    }

添加新訂單:

接收到websocket消息


免責聲明!

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



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