如何修改Jersey EventInput所使用的SSE事件分隔符?
解决非标准SSE分隔符的Jersey EventInput替代实现
遇到这种非标准SSE流的情况确实头疼,毕竟Jersey自带的EventInput是严格按照官方标准实现的。不过我们可以通过自定义一个替代类来解决这个问题,核心就是修改事件分隔符的解析逻辑。
核心实现思路
- 我们需要自定义一个类似
EventInput的类,重写其事件解析逻辑,将分隔符从标准的\r\n\r\n替换为\n - 要兼容SSE的字段规则:每个字段(比如
event、data、id、retry)是以换行分隔的,非标准流里每个事件的结束就是单独的\n - 处理流读取时的缓冲逻辑,确保能正确分割每个完整的事件
关键代码示例
以下是自定义解析逻辑的核心部分(你可以基于Jersey原生EventInput的源码结构进行修改):
import java.io.BufferedReader; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; public class CustomEventInput implements Closeable { private final InputStream inputStream; private BufferedReader reader; // 替换为目标流使用的非标准分隔符 private final String EVENT_DELIMITER = "\n"; public CustomEventInput(InputStream inputStream) { this.inputStream = inputStream; this.reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); } public InboundEvent read() throws IOException { StringBuilder eventContent = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { // 遇到分隔符,结束当前事件的读取 if (line.isEmpty() && EVENT_DELIMITER.equals("\n")) { break; } eventContent.append(line).append("\n"); } if (eventContent.length() == 0) { return null; // 流已读取完毕 } // 解析事件的各个字段 return parseEventFields(eventContent.toString()); } private InboundEvent parseEventFields(String rawEvent) { InboundEvent event = new InboundEvent(); String[] lines = rawEvent.split("\n"); for (String line : lines) { if (line.startsWith("event:")) { event.setName(line.substring(6).trim()); } else if (line.startsWith("data:")) { event.addData(line.substring(5).trim()); } else if (line.startsWith("id:")) { event.setId(line.substring(3).trim()); } else if (line.startsWith("retry:")) { try { event.setRetry(Long.parseLong(line.substring(6).trim())); } catch (NumberFormatException e) { // 处理无效的retry数值,可根据需求调整 } } // 自动忽略以冒号开头的注释行 } return event; } @Override public void close() throws IOException { reader.close(); inputStream.close(); } }
注意事项
- 测试边界场景:比如流末尾的不完整事件、连续的空分隔符、带有注释的事件行
- 集成Jersey Client:在发起请求后,使用
ClientResponse.readEntity(CustomEventInput.class)来获取自定义的事件输入流,替换原生的EventInput - 可扩展性:如果后续服务端修复为标准SSE格式,直接切换回原生
EventInput即可,无需大量修改代码
内容的提问来源于stack exchange,提问作者pinpinokio
相关产品推荐
相关产品推荐

