使用Jersey序列化Java 8流

如何使用Jersey序列化Java 8 java.util.Stream 。 我尝试编写MessageBodyWriter ,但我需要知道如何使用新的MessageBodyWriter为我的Stream编写(修饰)现有的MessageBodyWriters

 Stream get(){ return some stream of strings } public  class StreamMessageBodyWriter<Stream> implements MessageBodyWriter<Stream> { public void writeTo(.......){ //How can I get the handle to MessageBodyWriter that will write for type T, //so that I can 'collect' the 'java.util.Stream' and write it to //OutputStream } } 

但我需要知道如何使用新的MessageBodyWriter为我的Stream MessageBodyWriters (装饰)现有的MessageBodyWriters

您可以注入Providers并使用getMessagBodyWriter(...) ,传入所需的详细信息以查找该类型的特定writer。 例如

 @Provider public class StreamBodyWriter implements MessageBodyWriter { @Context private Providers providers; @Override public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return Stream.class.isAssignableFrom(type); } @Override public long getSize(Stream stream, Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return -1; } @Override public void writeTo(Stream stream, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { Object obj = stream.collect(Collectors.toList()); Class objType = obj.getClass(); MessageBodyWriter writer = providers.getMessageBodyWriter(objType, null, annotations, mediaType); writer.writeTo(obj, objType, null, annotations, mediaType, httpHeaders, entityStream); } } 

如果你看一下writeTo ,首先我调用collect然后获取返回的类型。 然后查找该类型的编写器,然后简单地委托给编写器。

这是一个测试

 @Path("stream") public class StreamResource { @GET @Produces(MediaType.APPLICATION_JSON) public Response getStream() { List myList = Arrays.asList( new Person("Stack"), new Person("Overflow"), new Person("Sam")); Stream stream = myList.stream() .filter(p -> p.name.startsWith("S")); return Response.ok(stream).build(); } public static class Person { public String name; public Person(String name) { this.name = name; } public Person() {} } } 

C:\>curl -v http://localhost:8080/api/stream
结果:
[{"name":"Stack"},{"name":"Sam"}]

顺便说一句,如果您计划在编写器中操作Stream,可能会考虑使用Interceptor 。 真的不会有所作为,但如果你想坚持单一责任原则,这就是Interceptor所用的,操纵请求体。


注意:以上是标准的JAX-RS

另外…

特别是对于Jersey,你也可以注入MessageBodyWorkers ,进行更具体的查找,甚至调用它的writeTo ,如果有的话,它将委托给所需的编写者。

根据使用流的目的(不使用stream.collect(Collectors.toList()) ),这篇有趣的文章展示了如何从数据库中序列化大数据 。

这是这样的……

 @GET @Produces( "application/json" ) public Response streamGeneratedUuids() { return getNoCacheResponseBuilder( Response.Status.OK ).entity( new StreamingOutput() { @Override public void write( OutputStream os ) throws IOException, WebApplicationException { try (PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(os))) ) { //iterate the java.util.stream and write to the OutputStream writer.print("...."); } } }).build(); } 

它没有用MessageBodyWriter实现,但在我看来可以改编。