近期有這麼乙個需求:
手機端需要展示乙個比較大的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 ...