在 Java 客戶端使用 OkHttp 監聽 SSE(Server-Sent Events) 的情況下,當服務端調用 SseEmitter.completeWithError(e)
,客戶端會觸發 EventSourceListener
的 onFailure()
方法(而不是 onError
)。
1. 服務端(Spring Boot)調用 completeWithError
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;@RestController
public class SseController {@GetMapping("/sse-stream")public SseEmitter streamEvents() {SseEmitter emitter = new SseEmitter();new Thread(() -> {try {for (int i = 0; i < 5; i++) {emitter.send(SseEmitter.event().data("Event " + i));Thread.sleep(1000);}// 模擬一個錯誤并主動關閉throw new RuntimeException("Server-side error!");} catch (Exception e) {emitter.completeWithError(e); // 觸發客戶端的 onFailure()}}).start();return emitter;}
}
2. 客戶端(Java + OkHttp)監聽 SSE
OkHttp 提供了 EventSource
類來監聽 SSE 事件,并需要實現 EventSourceListener
來接收回調。
關鍵方法
onOpen()
– 連接建立時觸發。onEvent()
– 收到服務器事件時觸發。onClosed()
– 服務器主動關閉(emitter.complete()
)時觸發。onFailure()
– 服務器調用completeWithError()
或網絡錯誤時觸發。
代碼示例
import okhttp3.*;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;
import okhttp3.sse.EventSources;public class SseClient {public static void main(String[] args) {OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url("http://localhost:8080/sse-stream").build();EventSource.Factory factory = EventSources.createFactory(client);factory.newEventSource(request, new EventSourceListener() {@Overridepublic void onOpen(EventSource eventSource, Response response) {System.out.println("SSE connected!");}@Overridepublic void onEvent(EventSource eventSource, String id, String type, String data) {System.out.println("Received event: " + data);}@Overridepublic void onClosed(EventSource eventSource) {System.out.println("SSE closed by server.");}@Overridepublic void onFailure(EventSource eventSource, Throwable t, Response response) {System.err.println("SSE error: " + t.getMessage());// 可以在這里重試}});}
}
3. 執行流程
- 服務端:
- 發送5條事件后,調用
emitter.completeWithError(e)
。
- 發送5條事件后,調用
- 客戶端:
- 收到5條正常事件(
onEvent()
)。 - 當服務端
completeWithError(e)
時,觸發onFailure()
,并打印錯誤信息。
- 收到5條正常事件(
4. 總結
服務端行為 | 客戶端(OkHttp)回調方法 |
---|---|
emitter.send(data) | onEvent() |
emitter.complete() | onClosed() |
emitter.completeWithError(e) | onFailure() |
網絡斷開/超時 | onFailure() |
因此,SseEmitter.completeWithError(e)
會觸發客戶端的 onFailure()
方法,而不是 onError
(這是瀏覽器 EventSource
的行為)。