伺服器端事件傳送SSE

2022-02-14 18:04:26 字數 2692 閱讀 6856

近期有這麼乙個需求:

手機端需要展示乙個比較大的pdf

而是把pdf轉成一張張的,然後再在手機上展示。

pdf轉,肯定是乙個比較慢的過程,最好能轉完一張就返回一張到前端。

so,此文要講的是 請求非同步多次返回的技術實現sse

當然,websocket也能做到,它可以雙向通訊,比sse(單向傳送)強大且複雜,sse好在比較簡單

全稱:server send event

其實嚴格地說,http 協議無法做到伺服器主動推送資料到客戶端的。只不過可以變通一下,就是伺服器向客戶端宣告,接下來要傳送的是流資料(stream)。

此時,客戶端不會關閉連線,會一直等著伺服器發過來的新的資料流。

sse 就是利用這種機制,使用流資訊向瀏覽器推送資訊。它基於 http 協議,目前除了 ie,其他瀏覽器都支援。

ie的話,也可以通過evensource.js來相容起來。

需要用到eventsource,並實現onmessage方法

if (!!window.eventsource) );

source.addeventlistener('open', function(e) , false);

source.addeventlistener('error', function(e) else

}, false);

} else

需要設定型別為event-stream

以上客戶端和服務端的**示例基於

做了如下修改:

1、原文示例**中,每個請求只返回了一次資料,伺服器每次發完資料斷開了連線。

但sse缺省會自動重連,所以客戶端不斷地重連(重新發請求)。瀏覽器f12 network,可以看到刷了很多請求

這和ajax長輪詢沒什麼區別了。

2、controller端處理完return返回之後,前端頁面會收到乙個error事件。瀏覽器接收到error事件後,sse又會自動重連,所以我加了乙個source.close();

當然這裡close不合理,後面再聊合理的做法

這裡需要知道的是:return之後長連線就斷開了,就不是我們想要的持續推送了。

修改後的**見github:

springmvc已經對這種非同步響應做了很好的封裝,我們可以直接返回callable、deferredresult或sseemitter 來更優雅地實現我們的需求。

返回callable的時候,spring做了這些事情

deferredresult的處理邏輯和callable返回差不多,只不過deferredresult的執行緒不由springmvc管理。

參考資料:

callable和deferredresult一般用於非同步返回單個結果;

sseemitter則可以非同步多次返回。

在使用sseemitter寫**前,再解決以下前面提到的乙個小問題 -- 合理地close掉eventsource。

前面的**裡面,為了避免controller中return後,瀏覽器重連,我們直接在error裡面把source給close掉了。

source.addeventlistener('error', function(e) else

}, false);

sseemitter有complete()方法,不過執行之後,瀏覽器也是會收到error事件,並重新請求鏈結;

那麼,最好的做法是:

controller處理返回完之後,通知請求端瀏覽器,告訴它資料都傳完了,由瀏覽器端主動去close掉eventsource。

經過上面一系列的分析,可以開始愉快地寫**了:

返回乙個自定義的event,type為finish,告知瀏覽器可以關閉連線了。

@responsebody

public sseemitter sseemittercall()

class testrun implements runnable

@override

public void run()

} catch (ioexception | interruptedexception e)

} }}增加處理finish事件的響應**

if (!!window.eventsource) );

source.addeventlistener('open', function(e) , false);

// 響應finish事件,主動關閉eventsource

source.addeventlistener('finish', function(e) , false);

source.addeventlistener('error', function(e) else

}, false);

} else

完整**見:

推薦閱讀:

server-sent events 教程

SSE 伺服器傳送事件

詳情檢視 sse 伺服器傳送事件 概述傳統的網頁都是瀏覽器向伺服器 查詢 資料,但是很多場合,最有效的方式是伺服器向瀏覽器 傳送 資料。比如,每當收到新的電子郵件,伺服器就向瀏覽器傳送乙個 通知 這要比瀏覽器按時向伺服器查詢 polling 更有效率。自定義事件 function connectti...

四 SOAP訊息建立傳送伺服器端

1.將編寫好的soap訊息傳送至伺服器端,並接受伺服器端訊息 string ns 1 建立服務 service 2 建立dispatch dispatchdispatch service.createdispatch new qname ns,firstwebserviceimplport soap...

socket伺服器端

伺服器 include winsock2.h include string.h include stdio.h include time.h include stdarg.h include stdlib.h pragma comment lib,ws2 32 void errexit const ...