Vert.x ReadStream <buffer>到InputStream

时间:2017-09-20 15:10:09

标签: jersey vert.x

我正在尝试使用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没有被调用并且正在等待它。

2 个答案:

答案 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),即:

  1. http请求在事件循环(由Netty)处理,因此必须在不同的线程(非事件循环)上调用ApplicationHandler.handle()方法
  2. 非阻止API必须转换为阻止InputStream。这是在NettyInputStream实施的。它利用了Netty的ByteBuf可以很容易地转换为InputStream这一事实,因此使用LinkedBlockingDeque将这些InputStream转换为单个。 (只是fyi,我不是100%确定提供者,事件循环线程,是否保证永远不会阻止哪个是错误。)
  3. 顺便说一句,这只是对传入数据的处理。对于响应,您必须实现OutputStream(由Jersey使用)到Vert.X非阻塞API的转换。

答案 1 :(得分:0)

需要两个组件。

  1. 您需要确保将使用vertx.executeBlocking阻止的任何内容的处理分开https://github.com/trajano/app-ms/blob/master/ms-engine/src/main/java/net/trajano/ms/engine/JaxRsRoute.java#L128

  2. 您需要处理两个事件:当新的数据缓冲区进入时以及何时结束。 https://github.com/trajano/app-ms/blob/master/ms-engine/src/main/java/net/trajano/ms/engine/JaxRsRoute.java#L123

  3. 您需要实现一个InputStream,它能够接收来自另一个线程的数据并在没有数据时阻塞,并且能够接收没有更多输入的消息。 https://github.com/trajano/app-ms/blob/master/ms-engine/src/main/java/net/trajano/ms/engine/internal/VertxBlockingInputStream.java