使用Jersey序列化Java 8流

Dhr*_*dna 6 java jax-rs jersey java-8 jersey-2.0

如何java.util.Stream<T>使用Jersey 序列化Java 8 .我试着写一个MessageBodyWriter,但我需要知道如何MessageBodyWritersMessageBodyWriter我的新作品来构建(装饰)Stream.

Stream<String> get(){
  return some stream of strings  
}

public <T> class StreamMessageBodyWriter<Stream<T>> 
           implements MessageBodyWriter<Stream<T>> {

  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<T>' and write it to 
    //OutputStream
  }
}
Run Code Online (Sandbox Code Playgroud)

Pau*_*tha 4

但我需要知道如何用新的东西来组合(装饰)现有的MessageBodyWriters东西MessageBodyWriterStream

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

@Provider
public class StreamBodyWriter implements MessageBodyWriter<Stream> {
    
    @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<String, Object> 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);
        
    }
}
Run Code Online (Sandbox Code Playgroud)

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

这是一个测试

@Path("stream")
public class StreamResource {
    
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getStream() {
        List<Person> myList = Arrays.asList(
                              new Person("Stack"), 
                              new Person("Overflow"),
                              new Person("Sam"));
        Stream<Person> 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() {}
    }
}
Run Code Online (Sandbox Code Playgroud)

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

顺便说一句,如果您计划在编写器中操作 Stream,也许可以考虑使用Interceptor。实际上不会有什么区别,但如果您想坚持单一职责原则,这就是Interceptor操作请求正文的目的。


注:以上为标准JAX-RS

或者...

特别是对于 Jersey,您还可以注入MessageBodyWorkers,以进行更具体的查找,甚至调用它writeTo,这将委托给所需的编写器(如果存在)。

  • `stream.collect(Collectors.toList())` 违背了使用流的目的。如果我有一个包含大量元素的流,我无法将它们全部组装到内存集合中;这就是首先使用 Java 8 流的原因之一。 (3认同)