[英]consume Spring SSE with Xamarin
我有一個 spring 啟動后端,我想為其實現一個 SSE 端點。 我想使用基於 Xamarin Forms 的應用程序使用此端點。
我設法為雙方實施了一些示例,但是,我沒有設法在應用程序上收到任何消息。
對於后端部分,我實現了以下示例:
@RequestMapping(value = "/event-stream", method = RequestMethod.GET)
public ResponseEntity<ResponseBodyEmitter> streamEvents() {
ResponseBodyEmitter emitter = new ResponseBodyEmitter();
executor.execute(() -> {
try {
for (int i = 0; i < 30; i++) {
Thread.sleep(2000);
var msg = new ResponseTestObject("this is a message from " + new Date(), i);
emitter.send(msg, MediaType.APPLICATION_JSON);
}
emitter.complete();
} catch (Exception ex) {
emitter.completeWithError(ex);
}
});
return new ResponseEntity<>(emitter, HttpStatus.OK);
}
@AllArgsConstructor
public static class ResponseTestObject {
public String message;
public int id;
}
注意:我有意以達到默認 30 秒超時的方式實現它。 使用 postman 調用此方法,它將加載所述 30 秒並同時顯示所有已發送的消息:
{
"message": "this is a message from Thu May 05 11:36:25 CEST 2022",
"id": 0
}{
"message": "this is a message from Thu May 05 11:36:27 CEST 2022",
"id": 1
}
[...]
{
"message": "this is a message from Thu May 05 11:36:51 CEST 2022",
"id": 13
}{
"message": "this is a message from Thu May 05 11:36:53 CEST 2022",
"id": 14
}
在我的應用程序部分,我使用了 ServiceStack ServerEventsClient:
EventClient = new ServerEventsClient(BackendConnector.BACKEND_HOST + "/events/") {
OnMessage = OnMessage,
OnException = (ex) => {
Console.WriteLine("OnException: " + ex.Message);
}
};
// another REST backend connection is made previously in the app and I use its session cookie for authentication
EventClient.ServiceClient.SetCookie(BackendConnector.SESSION_COOKIE_VALUE, BackendConnector.BackendSessionCookieId);
EventClient.Start();
啟動客戶端后,我讓它定期發布這樣的狀態:
Console.WriteLine("SSE " + EventClient.Status);
我可以看到以下內容:
附加說明:我還有一個使用 SseEmitter 的服務器端測試實現。 在這種情況下,我也可以在“訂閱”期間看到應用程序請求,但它會在某個時候超時並出現異常,並且客戶端狀態永遠不會離開“開始”
我的第一個問題顯然是:我錯過了什么,我永遠不會收到消息?
我的第二個問題是:為什么它首先超時? 根據文檔,它會定期發送心跳。 我需要在 spring 端使用不同的方法嗎? 或者我是否需要為心跳實現一個單獨的端點?
感謝您的幫助!
編輯:
按照@mythz 的回答並接受在這里使用 ServiceStack 不是一個好主意,我遵循以下示例並使用標准 HttpClient 和 StreamReader 實現了一種簡單的方法: https://makolyte.com/event-driven-do.net-how -to-consume-an-sse-endpoint-with-httpclient/
但是,這導致了我之前使用 postman 或我的瀏覽器遇到的相同問題。 30 秒超時后,所有消息將批量發送。 因此我也改變了后端部分並使用 spring web 助焊劑代替:
public Flux<ServerSentEvent<String>> streamEvents() {
return Flux.interval(Duration.ofSeconds(1))
.map(sequence -> {
var msg = new ResponseTestObject("this is a message from " + new Date(), Math.toIntExact(sequence));
ObjectMapper mapper = new ObjectMapper();
try {
return ServerSentEvent.<String>builder()
.id(String.valueOf(sequence))
.event("periodic-event")
.data(mapper.writeValueAsString(msg))
.build();
} catch (JsonProcessingException e) {
return null;
}
});
}
我強烈建議您不要將 ServiceStack 的ServerEventsClient
與 ServiceStack 的服務器事件功能以外的任何東西一起使用,這是它所有類型化的服務器事件客戶端設計用於處理的功能。
例如,為了啟用斷開的網絡連接和自動重試連接功能,客戶端會定期發回心跳。 這只是 ServiceStack 實現中的一個特性,因為 SSE 標准中沒有這樣的概念。
這只是一個例子,基本上C# 服務器事件客戶端中的每個高層都使用了 ServiceStack 服務器功能,這在任何其他第 3 方實現中都不存在。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.