【问题标题】:Serialize Java 8 Stream with Jersey使用 Jersey 序列化 Java 8 流
【发布时间】:2015-03-24 04:24:54
【问题描述】:

如何使用 Jersey 序列化 Java 8 java.util.Stream<T>。我试图写一个MessageBodyWriter,但我需要知道如何为我的Stream 用一个新的MessageBodyWriter 组合(装饰)现有的MessageBodyWriters

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
  }
}

【问题讨论】:

    标签: java jersey jax-rs java-8 jersey-2.0


    【解决方案1】:

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

    您可以只注入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);
            
        }
    }
    

    如果您查看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() {}
        }
    }
    

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

    顺便说一句,如果您打算在 writer 中操作 Stream,不妨考虑使用 Interceptor。不会有什么不同,但如果你想坚持单一责任原则,这就是Interceptor 的用途,操纵请求正文。


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

    或者...

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

    【讨论】:

    • 非常感谢。 Providers 注入是我一直在寻找的。我仍然需要找到一种不收集列表的方法,因为我想避免将列表实现到内存中,但这是我将要做的事情。这真的很有帮助。
    • stream.collect(Collectors.toList()) 违背了使用流的目的。如果我有一个包含大量元素的流,我无法将它们全部组装到内存集合中;这就是首先使用 Java 8 流的原因之一。
    【解决方案2】:

    符合使用流的目的(不使用stream.collect(Collectors.toList())),有这篇有趣的文章显示how to serialize large data from a database

    是这样的……

    @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 实现的,但我认为可以适应。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-07
      • 2017-03-12
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多