ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

OkHttp Server-Sent Events(SSE)模块实战:EventSource 事件流接入指南

OkHttp Server-Sent Events(SSE)模块实战:EventSource 事件流接入指南 OkHttp Server-Sent EventsSSE模块实战EventSource 事件流接入指南【免费下载链接】okhttpA meticulous HTTP client for the JVM, Android, and GraalVM.项目地址: https://gitcode.com/gh_mirrors/okh/okhttpServer-Sent EventsSSE是服务端通过 HTTP 长连接向客户端单向推送事件的标准协议适合实时通知、进度推送、行情更新等场景。OkHttp 在独立模块okhttp-sse中提供了对 SSE 的实验性支持本文基于仓库中 okhttp-sse/README.md 及其源码系统讲解如何通过 OkHttp 的EventSourceAPI 订阅事件流、解析标准 SSE 帧并处理重连、鉴权与超时等工程问题。读完本文你将掌握 SSE 流式推送在 JVM / Android 应用中的完整接入方案。模块概览与依赖引入okhttp-sse是 OkHttp 官方仓库中独立发布的实验性模块对应 okhttp-sse/Module.md 中 Support for server-sent events 的描述。需要注意该 API 尚不稳定随时可能变更README 明确标注 Experimental support for server-sent events. API is not considered stable and may change at any time.。添加依赖在 Gradle 项目中通过testImplementation引入依赖当前仓库版本为 5.5.0testImplementation(com.squareup.okhttp3:okhttp-sse:5.5.0)注意README 中该依赖声明在testImplementation配置下实际用于生产环境时应按项目需要改为implementation。该模块以okhttp3为核心依赖JPMS 模块声明见 okhttp-sse/src/main/java9/module-info.java模块名okhttp3.sserequires okhttp3并exports okhttp3.sse因此 Java 9 模块化项目可直接引用。核心 API 全景okhttp-sse对外只暴露三个类全部位于okhttp3.sse包二进制 API 定义见 okhttp-sse/api/okhttp-sse.api。1. EventSource事件源句柄EventSource.kt 定义了两个方法request(): Request—— 返回发起该事件源的原始请求cancel()—— Immediately and violently release resources立即且彻底地释放该事件源占用的资源若事件源已关闭或已取消此操作无副作用。其内部接口EventSource.Factory是创建事件源的入口fun interface Factory { fun newEventSource( request: Request, listener: EventSourceListener, ): EventSource }创建事件源即会发起异步连接流程连接成功或失败后listener会收到通知调用方在不再使用时必须主动 cancel返回的事件源。2. EventSourceListener事件回调EventSourceListener.kt 是一个抽象类四个回调方法均带默认空实现可按需覆写回调参数触发时机onOpeneventSource,response事件源被远端接受可以开始传输事件onEventeventSource,id,type,data收到一条完整事件id/type可能为 nullonClosedeventSource事件源正常关闭此后不再有任何回调onFailureeventSource,t,response读写网络出错导致关闭可能已丢失部分事件此后不再有回调3. EventSources工厂与工具入口EventSources.kt 是object单例提供两个JvmStatic方法createFactory(callFactory: Call.Factory): EventSource.Factory—— 由OkHttpClient其实现了Call.Factory创建事件源工厂processResponse(response, listener)—— 在已有 OkHttpResponse之上直接挂接 SSE 处理用于自行管理 Call 的场景。createFactory内部有一个关键细节如果请求头中没有显式设置Accept会自动补上Accept: text/event-stream若已设置则保留原值。这一行为有测试覆盖见下节。最小可运行示例结合 EventSourceHttpTest.kt 中的用法一个完整的接入流程如下import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.sse.EventSource import okhttp3.sse.EventSourceListener import okhttp3.sse.EventSources.createFactory import okhttp3.Response val client OkHttpClient() // 1. 创建事件源工厂 val factory createFactory(client) // 2. 定义监听器 val listener object : EventSourceListener() { override fun onOpen(eventSource: EventSource, response: Response) { println(连接已建立) } override fun onEvent( eventSource: EventSource, id: String?, type: String?, data: String, ) { println(收到事件: id$id, type$type, data$data) } override fun onClosed(eventSource: EventSource) { println(连接已关闭) } override fun onFailure( eventSource: EventSource, t: Throwable?, response: Response?, ) { println(连接失败: $t) } } // 3. 发起请求并订阅 val request Request.Builder() .url(https://example.com/events) .build() val eventSource: EventSource factory.newEventSource(request, listener) // 4. 不再使用时释放资源 // eventSource.cancel()事件解析协议详解SSE 帧的解析逻辑在 ServerSentEventReader.kt 中实现。它用 Okio 的Options一次性匹配 20 种前缀模式\r\n、\r、\n三种行结束符分别与data、id、event、retry字段组合支持多行 data多条data:行会被累积并以换行符拼接。测试multiline用例验证了data: YHOO、data: 2、data: 10解析为YHOO\n2\n10见 ServerSentEventIteratorTest.ktevent 类型event: add指定事件类型随onEvent的type参数返回id 与重连id:行更新lastId并在事件携带单独的id行无冒号值会清空 idretry 指令retry:解析为毫秒数通过onRetryChange回调通知——但 RealEventSource.kt 中明确忽略该值不做自动重连注释 Ignored. We do not auto-retry.注释与空行以:开头的注释行被跳过data为空的帧不会触发onEventcompleteEvent中data.size 0L时直接返回。processNextEvent()每次处理一条事件EOF 时返回false驱动整个读取循环。底层工作流程RealEventSourceRealEventSource.kt 同时实现了EventSource、ServerSentEventReader.Callback与 OkHttp 的Callback核心流程如下connectcallFactory.newCall(request).enqueue(this)异步发起请求onResponse 校验响应不成功!isSuccessful或Content-Type不是text/event-stream校验逻辑见isEventStream()要求type text subtype event-stream时直接回调onFailure取消全量超时SSE 是长连接call?.timeout()?.cancel()取消整次调用的超时定时器避免长连接被误杀剥离响应体response.stripBody()替换 body保证外部回调无法读到真实流数据读取循环listener.onOpen后在while (!canceled reader.processNextEvent())中持续消费事件收尾读取异常时回调onFailure被取消时回调onFailure(IOException(canceled))正常读到 EOF 时回调onClosed。因此事件回调线程与 OkHttp 异步回调线程一致即 OkHttp 的 Dispatcher 线程开发者不应在onEvent中执行耗时操作。关键边界行为与测试验证仓库测试 EventSourceHttpTest.kt 覆盖了以下工程要点场景行为测试方法正常事件流收到onOpen→onEvent(null, null, hey)→onCloseevent错误 Content-TypeonFailure(Invalid content-type: text/plain)badContentType非 2xx 状态码onFailure携带响应体信息badResponseCodeAccept头自动补齐未设置时发送Accept: text/event-stream已设置则保留如text/plainsetsMissingAccept/retainsAccept连接建立后的全量超时callTimeout(250ms)不影响已建立的长连接.bodyDelay(500ms)仍能收到事件fullCallTimeoutDoesNotApplyOnceConnected连接建立前的全量超时响应头延迟 500ms 时按超时失败fullCallTimeoutAppliesToSetup鉴权重试401 后通过Authenticator携带Authorization: XYZ重试成功sseReauths事件回调中 cancel在onOpen中 cancel 会短路读取循环回调onFailure(canceled)cancelInEventShortCircuits其中sseReauths证明SSE 连接同样走 OkHttp 的拦截器与重试链路——只要配置了Authenticator401 响应会自动触发携带凭据的重试无需手动处理而没有Authenticator时 401 直接导致onFailuresseWithoutAuthenticator。测试还通过EventRecorder验证了一次完整 SSE 调用会依次触发CallStart→ … →ResponseBodyStart→ResponseBodyEnd→CallEnd等标准 CallEvent 事件见eventListenerEvents说明 SSE 完全复用 OkHttp 的调用事件体系便于埋点观测。使用建议与注意事项基于源码与测试给出如下工程建议必须调用cancel()事件源不再使用时如页面销毁、任务取消务必调用EventSource.cancel()以释放连接资源取消路径会在onFailure中以IOException(canceled)收尾。主动处理重连模块不做自动重连retry指令被忽略服务端断流后应自行决定退避策略并重新newEventSource。校验 Content-Type服务端必须返回text/event-stream否则会收到Invalid content-type失败回调可通过Authenticator/拦截器链路处理鉴权 401 重试。注意 API 不稳定作为实验性模块升级 OkHttp 版本时需留意EventSource相关 API 的变更。长连接与超时连接建立后全量调用超时会被取消但读取数据仍受底层 socket 读超时约束可结合 OkHttpClient 的 read 超时配置。相关资源模块说明okhttp-sse/README.md、okhttp-sse/Module.md对外 APIokhttp-sse/api/okhttp-sse.api核心实现EventSource.kt、EventSourceListener.kt、EventSources.kt、RealEventSource.kt、ServerSentEventReader.kt测试用例EventSourceHttpTest.kt、ServerSentEventIteratorTest.kt【免费下载链接】okhttpA meticulous HTTP client for the JVM, Android, and GraalVM.项目地址: https://gitcode.com/gh_mirrors/okh/okhttp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表