将文档流发送到Jersey @POST端点

Nic*_*zza 9 java rest streaming jersey

我希望能够一堆文档流发送到Web服务.这将节省Http请求/响应开销并专注于文档本身.

在python中你可以这样做:

r = requests.post('https://stream.twitter.com/1/statuses/filter.json',
    data={'track': 'requests'}, auth=('username', 'password'),
    stream=True)

for line in r.iter_lines():
    if line: # filter out keep-alive new lines
        print json.loads(line)
Run Code Online (Sandbox Code Playgroud)

我正在寻找有人将请求流式传输到泽西岛休息api的示例.我希望看到客户端和服务器端显示它正常工作.但我很难找到一个例子.

理想情况下,该示例将显示:

Client:
  Open request
  Iterate over huge document list
    Write document to open request stream
  Close request

Server:
  @POST method
    Open entity stream
    Iterate over entity stream while next document is available
        Process document
    Close entity stream              
Run Code Online (Sandbox Code Playgroud)

如果我们做对了,您将在服务器上处理实体,同时仍然在客户端上发送它们!巨大的胜利!

jdg*_*day 6

实现此目的的最简单方法之一是让Jersey为POST POST处理程序提供一个InputStreamHTTP POST主体.该方法可以使用InputStream您选择的JSON解析器来解析然后处理每个对象.

在下面的示例中,Jackson ObjectReader生成了一个MappingIterator解析并处理Person阵列中的每个文档,因为它被传递到服务器

/**
 * Parse and process an arbitrarily large JSON array of Person documents
 */
@Path("persons")
public static class PersonResource {

    private static final ObjectReader reader = new ObjectMapper().readerFor(Person.class);

    @Path("inputstream")
    @Consumes("application/json")
    @POST
    public void inputstream(final InputStream is) throws IOException {
        final MappingIterator<Person> persons = reader.readValues(is);
        while (persons.hasNext()) {
            final Person person = persons.next();
            // process
            System.out.println(person);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

同样,Jersey客户端框架可以在配置Jackson时发送文档流ObjectMapper.以下示例使用Jersey Test框架演示了这一点.客户端流式传输一个任意大的Person文档迭代器

public class JacksonStreamingTest extends JerseyTest {

    @Override
    protected Application configure() {
        return new ResourceConfig(PersonResource.class, ObjectMapperProvider.class);
    }

    /**
     * Registers the application {@link ObjectMapper} as the JAX-RS provider for application/json
     */
    @Provider
    @Produces(MediaType.APPLICATION_JSON)
    public static class ObjectMapperProvider implements ContextResolver<ObjectMapper> {

        private static final ObjectMapper mapper = new ObjectMapper();

        public ObjectMapper getContext(final Class<?> objectType) {
            return mapper;
        }
    }

    @Override
    protected void configureClient(final ClientConfig config) {
        config.register(ObjectMapperProvider.class);
    }

    @Test
    public void test() {
        final Set<Person> persons = Collections.singleton(Person.of("Tracy", "Jordan"));
        final Response response = target("persons/inputstream").request().post(Entity.json(persons.iterator()));
        assertThat(response.getStatus()).isEqualTo(204);
    }
}
Run Code Online (Sandbox Code Playgroud)