Jersey Vert.x ReadStream<;缓冲区>;输入流

Jersey Vert.x ReadStream<;缓冲区>;输入流,jersey,vert.x,Jersey,Vert.x,我试图用Jersey设置Vert.X来处理POST数据(不一定是表单数据) JerseyContainerRequest.setEntityStream接收一个InputStream,这正是我试图构建的。但是,如果不使用bodyHandler或我自己的自定义方法将整个内容读取到内存中,我似乎无法绕过传递数据的过程,该方法会执行类似的操作,但会限制输入 final Buffer body = Buffer.buffer(); event .handler(buffe

我试图用Jersey设置Vert.X来处理POST数据(不一定是表单数据)

Jersey
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()来节省一些内存。但它有整个身体


我不想让整个身体都流下来。我已经尝试了一些非常粗糙和糟糕的代码,但最终都不起作用,因为它阻止了事件循环,因为
处理程序没有被调用并且正在等待它。

这是一个很好的问题需要解决:)
你可以从中得到灵感 其中,Jersey与Netty实现了集成

我相信解决了完全相同的问题(尽管对于不同的Web服务器,在本例中是Netty),即:

  • http请求在事件循环(由Netty)上处理,因此必须在不同的线程(非事件循环)上调用
    ApplicationHandler.handle()
    方法
  • 非阻塞API必须转换为阻塞
    InputStream
    。这是在
    NettyInputStream
    上实现的。它利用了这样一个事实,即Netty的
    ByteBuf
    可以很容易地转换为
    InputStream
    ,因此通过使用
    LinkedBlockingDeque
    这些InputStreams可以转换为单个InputStream。(仅供参考,我不能100%确定是否保证提供程序(事件循环线程)永远不会阻塞这将是一个bug。)

  • 顺便说一下,这只是对传入数据的处理。对于响应,您必须实现将
    OutputStream
    (Jersey使用)转换为Vert.X非阻塞API。

    需要两个组件

  • 您需要确保使用
    vertx.executeBlocking
    将任何可能阻塞的处理分开

  • 您需要处理两个事件:数据的新缓冲区进入时和结束时

  • 您需要实现一个InputStream,该InputStream能够在没有数据时从另一个线程和块接收数据,并能够接收没有更多输入的消息。


  • 谢谢,我也调查过了。我的一次尝试与之类似,但它仍然会阻塞,因为“take()”会阻塞。我不明白。那很好
    take()
    正在阻塞(这是
    InputStream.read()
    的约定)。重要的部分是我在[1]中描述的,
    ApplicationHandler.handle()
    必须委托给不同的线程。因此,另一个线程调用了
    take()
    方法,并且一切工作正常。除非Jersey附带了非阻塞API,否则别无选择,但这并没有发生(很不幸,但很接近)。正确,这是最接近的一个。(我现在刚让它工作起来)