使用 Jersey 序列化 Java 8 流 [英] Serialize Java 8 Stream with Jersey

查看:26
本文介绍了使用 Jersey 序列化 Java 8 流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

流<字符串>得到(){返回一些字符串流}公共<T>类 StreamMessageBodyWriter<Stream<T>>实现 MessageBodyWriter<Stream<T>>{公共无效 writeTo(.......){//如何获取将为类型 T 编写的 MessageBodyWriter 的句柄,//这样我就可以'收集''java.util.Stream<T>'并将其写入//输出流}}

解决方案

但我需要知道如何为我的 Stream

使用新的 MessageBodyWriter 组合(装饰)现有 MessageBodyWriters

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

@Provider公共类 StreamBodyWriter 实现 MessageBodyWriter;{@语境私人提供者提供者;@覆盖public boolean isWriteable(Class<?> type, Type genericType,Annotation[] 注释,MediaType mediaType) {返回 Stream.class.isAssignableFrom(type);}@覆盖public long getSize(Stream stream, Class<?> type, Type genericType,Annotation[] 注释,MediaType mediaType) { return -1;}@覆盖public void writeTo(Stream stream, Class<?> type, Type genericType,Annotation[] 注释,MediaType mediaType,多值映射<字符串,对象>httpHeaders、OutputStream 实体流)抛出 IOException,WebApplicationException {对象 obj = stream.collect(Collectors.toList());类<?>objType = obj.getClass();MessageBodyWriter writer = providers.getMessageBodyWriter(objType,空,注释,媒体类型);writer.writeTo(obj, objType, null, 注释,媒体类型,httpHeaders,实体流);}}

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

这是一个测试

@Path(流")公共类 StreamResource {@得到@Produces(MediaType.APPLICATION_JSON)公共响应 getStream() {列出<人员>myList = Arrays.asList(新人(堆栈"),新人(溢出"),新人(山姆"));流<人>流 = myList.stream().filter(p -> p.name.startsWith(S"));返回 Response.ok(stream).build();}公共静态类人{公共字符串名称;public Person(String name) { this.name = name;}公共人(){}}}

<块引用>

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

顺便说一句,如果您打算在编写器中操作 Stream,可以考虑使用 拦截器.真的不会有什么不同,但如果你想坚持单一职责原则,这就是 Interceptor 的用途,操纵请求正文.


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

或者...

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

How can I serialize a Java 8 java.util.Stream<T> with Jersey. I tried to write a MessageBodyWriter, but I need to know how to compose (decorate) existing MessageBodyWriters with a new MessageBodyWriter for my 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
  }
}

解决方案

but I need to know how to compose (decorate) existing MessageBodyWriters with a new MessageBodyWriter for my Stream

You can just inject Providers and use getMessagBodyWriter(...), passing in the required details to lookup the specific writer for that type. For example

@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);
        
    }
}

If you look at the writeTo, first I call collect then get the returned type. Then lookup the writer for that type, then simply delegate to the writer.

Here is a test

@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:>curl -v http://localhost:8080/api/stream
Result:
[{"name":"Stack"},{"name":"Sam"}]

As an aside, if you plan on manipulating the Stream in the writer, maybe look into using an Interceptor. Won't make a difference really, but if you want to stick to the Single Responsibility Principle, this is what the Interceptor is for, manipulating the request body.


Note: the above is standard JAX-RS

Alternatively...

Specifically with Jersey, you can also inject MessageBodyWorkers, for more specific lookup, and even calling its writeTo, which will delegate to the required writer, if one exsists.

这篇关于使用 Jersey 序列化 Java 8 流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆