我正在尝试使用Jersey设置Vert.X来处理POST数据(不一定是表单数据)。
泽西岛ContainerRequest.setEntityStream
接收InputStream
,这正是我想要建立的。但是,我似乎无法通过使用bodyHandler
或我自己的自定义方法将整个内容读入内存来传递数据,但该方法执行类似操作但限制了输入
final Buffer body = Buffer.buffer();
event
.handler(buffer -> {
if (!event.response().headWritten()) {
body.appendBuffer(buffer);
if (body.length() > 10 * 1024 * 1024) {
event.response()
.setStatusCode(REQUEST_ENTITY_TOO_LARGE.getStatusCode())
.setStatusMessage(REQUEST_ENTITY_TOO_LARGE.getReasonPhrase())
.end();
}
}
})
.endHandler(aVoid -> {
request.setEntityStream(new VertxBufferInputStream(body));
appHandler.handle(request);
});
VertxBufferInputStream
是VertXbuffer的简单包装器。只是为了避免转换为ByteArrayInputStream()来节省一些内存。但它有整个身体。
我想避免拥有整个身体并让它流式传输。我已经尝试了一些非常hacky和糟糕的代码,最终无效,因为它阻止了事件循环,因为handler
没有被调用并且正在等待它。
答案 0 :(得分:0)
这样一个美丽的问题要解决:) 你可以在https://github.com/jersey/jersey/blob/12e5d8bdf22bcd2676a1032ed69473cf2bbc48c7/containers/netty-http/src/main/java/org/glassfish/jersey/netty/httpserver/JerseyHttp2ServerHandler.java#L124获得灵感 泽西与Netty的整合实施。
我相信已经解决了完全相同的问题(尽管对于不同的网络服务器,在这种情况下是Netty),即:
ApplicationHandler.handle()
方法InputStream
。这是在NettyInputStream
实施的。它利用了Netty的ByteBuf
可以很容易地转换为InputStream
这一事实,因此使用LinkedBlockingDeque
将这些InputStream转换为单个。 (只是fyi,我不是100%确定提供者,事件循环线程,是否保证永远不会阻止哪个是错误。)顺便说一句,这只是对传入数据的处理。对于响应,您必须实现OutputStream
(由Jersey使用)到Vert.X非阻塞API的转换。
答案 1 :(得分:0)
需要两个组件。
您需要确保将使用vertx.executeBlocking
阻止的任何内容的处理分开https://github.com/trajano/app-ms/blob/master/ms-engine/src/main/java/net/trajano/ms/engine/JaxRsRoute.java#L128
您需要处理两个事件:当新的数据缓冲区进入时以及何时结束。 https://github.com/trajano/app-ms/blob/master/ms-engine/src/main/java/net/trajano/ms/engine/JaxRsRoute.java#L123
您需要实现一个InputStream,它能够接收来自另一个线程的数据并在没有数据时阻塞,并且能够接收没有更多输入的消息。 https://github.com/trajano/app-ms/blob/master/ms-engine/src/main/java/net/trajano/ms/engine/internal/VertxBlockingInputStream.java