我需要订阅 SSE(服务器发送事件)。我知道标准规定事件之间的分隔符应该是“\r\n\r\n” - 检查此处语法中的“行尾”:
https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream
但是我应该使用的流不遵循标准并用“\n”分隔。
我决定对 Jersey EventInput 类进行替代实现,您可以在此处看到:
因此,我的实现将复制 EventInput,唯一的区别是指定的分隔符。它看起来像:
public class MyEventInput extends ChunkedInput<InboundEvent> {
/**
* SSE event chunk parser - SSE chunks are delimited with a fixed "\n" and "\r\n\r\n" delimiter in the response stream.
*/
private static final ChunkParser SSE_EVENT_PARSER = ChunkedInput.createMultiParser("\n", "\r\n\r\n");
编译器完全接受我的实现,但是当我尝试运行它时,它不起作用!它卡在以下行中:
final MyEventInput eventInput = target.register(SseFeature.class)
.request().get(MyEventInput.class);
如果我执行以下操作,它就可以正常工作:
final EventInput eventInput = target.register(SseFeature.class)
.request().get(EventInput.class);
我开始调试,发现 Jersey 使用一个名为 MessageBodyFactory 的类,它会进行如下检查:
if (isCompatible(model, c, mediaType))
和
if (model.isReadable(c, t, as, mediaType))
他们检查你的类(class)是否是有效的读者。有效的读者是通过以下方式获得的(至少在我看来,在调试时......):
final Set<MessageBodyReader> customMbrs = Providers.getCustomProviders(injectionManager, MessageBodyReader.class);
final Set<MessageBodyReader> mbrs = Providers.getProviders(injectionManager, MessageBodyReader.class);
所以我的问题是...如何将 MyEventInput 注册为有效的读取器,以便我可以使用它来订阅以自定义分隔符分隔的 SSE 流?
最佳答案
好吧,由于我没有找到其他解决方案,我只是用反射“破解”了 Jersey 库,并为 EventInput 类指定了不同的解析器。这是我的做法(在实例化 EventInput 之前,您必须重新定义 SSE_EVENT_PARSER 字段...):
Field f = EventInput.class.getDeclaredField("SSE_EVENT_PARSER");
f.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);
f.set(null, ChunkedInput.createMultiParser("\n", "\r\n\r\n"));
final EventInput eventInput = target.request().get(EventInput.class);
关于java - 如何更改 Jersey EventInput 使用的分隔符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49878543/