我最近在 JAX-RS 应用程序中从使用 Jersey 切换到 CXF。我还使用 StreamingOutput 输出我自己的流,因为流中包含的数据需要大约 20 秒才能创建,并且可以由客户端部分处理。这在 Jersey 中一切正常,但我现在已经切换到使用 CXF 返回 JAXB bean 并且无法获得流媒体行为。对于 Jersey,我必须设置 jersey.config.contentLength.buffer.server
至 0
并冲洗 OutputStream
将数据发送给客户端,但我找不到 CXF 的等效项。我试过写一个 Interceptor
基于 StreamInterceptor
例如,但 write
Message
的方法的 OutputStream
在所有处理完成之前不会被调用。 JAXB bean 包含一个 Collection
带自定义 Iterator
在数据可用时提供数据。我可以看到数据在调试器中被缓冲。
如何使用 CXF 流式传输 JAXB bean?
最佳答案
我设法用 Jackson 和我自己的 MessageBodyWriter、BeanSerializerModifier 和 JsonSerializer 来做到这一点。我仍然需要找到一种使用 XML 的方法。
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
/**
* Created by jayen on 17/12/13.
*/
@SuppressWarnings({"DefaultFileTemplate"})
@Produces({"application/json", "application/*+json"})
@Provider
public class ResponseJSONWriter implements MessageBodyWriter<Response> {
@Override public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return Response.class.isAssignableFrom(type);
}
@Override
public long getSize(Response response, Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
return -1;
}
@Override
public void writeTo(Response response, Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
throws IOException, WebApplicationException {
try {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JaxbAnnotationModule());
mapper.setSerializerFactory(
mapper.getSerializerFactory().withSerializerModifier(new BeanSerializerModifier() {
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc,
JsonSerializer<?> serializer) {
return new FlushingSerializer<>(serializer);
}
}));
mapper.writeValue(entityStream, response);
} catch (Throwable e) {
e.printStackTrace();
}
}
private class FlushingSerializer<T> extends JsonSerializer<T> {
private final JsonSerializer<T> serializer;
public FlushingSerializer(JsonSerializer<T> serializer) {
this.serializer = serializer;
}
@Override public void serialize(T value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
serializer.serialize(value, jgen, provider);
jgen.flush();
}
}
}
关于stream - 无缓冲 CXF(无内容长度 header ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20620757/