用 Jersey 序列化 Java 8 Stream
Serialize Java 8 Stream with Jersey
如何使用 Jersey 序列化 Java 8 java.util.Stream<T>
。我试图写一个 MessageBodyWriter
,但我需要知道如何为我的 Stream
.
编写(装饰)现有的 MessageBodyWriters
和新的 MessageBodyWriter
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
您可以只注入 Providers
and use 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:\>curl -v http://localhost:8080/api/stream
Result:
[{"name":"Stack"},{"name":"Sam"}]
顺便说一句,如果您打算在 writer 中操作 Stream,不妨考虑使用 Interceptor。真的不会有什么不同,但如果你想坚持单一责任原则,这就是 Interceptor
的目的,操纵请求主体。
注:以上为标准JAX-RS
或者...
特别是对于 Jersey,您还可以注入 MessageBodyWorkers
,以进行更具体的查找,甚至调用它的 writeTo
,如果存在,它将委托给所需的编写器。
符合使用流的目的(不使用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 实现的,但我认为可以进行调整。
如何使用 Jersey 序列化 Java 8 java.util.Stream<T>
。我试图写一个 MessageBodyWriter
,但我需要知道如何为我的 Stream
.
MessageBodyWriters
和新的 MessageBodyWriter
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 newMessageBodyWriter
for myStream
您可以只注入 Providers
and use 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:\>curl -v http://localhost:8080/api/stream
Result:
[{"name":"Stack"},{"name":"Sam"}]
顺便说一句,如果您打算在 writer 中操作 Stream,不妨考虑使用 Interceptor。真的不会有什么不同,但如果你想坚持单一责任原则,这就是 Interceptor
的目的,操纵请求主体。
注:以上为标准JAX-RS
或者...
特别是对于 Jersey,您还可以注入 MessageBodyWorkers
,以进行更具体的查找,甚至调用它的 writeTo
,如果存在,它将委托给所需的编写器。
符合使用流的目的(不使用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 实现的,但我认为可以进行调整。