stream - 无缓冲 CXF(无内容长度 header )

标签 stream jaxb jersey cxf flush

我最近在 JAX-RS 应用程序中从使用 Jersey 切换到 CXF。我还使用 StreamingOutput 输出我自己的流,因为流中包含的数据需要大约 20 秒才能创建,并且可以由客户端部分处理。这在 Jersey 中一切正常,但我现在已经切换到使用 CXF 返回 JAXB bean 并且无法获得流媒体行为。对于 Jersey,我必须设置 jersey.config.contentLength.buffer.server0并冲洗 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/

相关文章:

java - 如何将 Jersey 应用程序部署到远程 Tomcat 服务器

java - 如何从 angularjs 和 CORS 支持将文件上传到 Jersey

C FILE 流实现

binding - 编码时,为什么 JAXB 不为具有固定值的必需属性调用 getter 方法?

JaxB 生成的 XML 也有其他模式的命名空间

java - 生成实现接口(interface)的 JAXB 类

eclipse - tomcat 上的 java web 服务 (jersey) 仅在从 eclipse 运行时才有效

testing - STREAM 基准的向量函数

javascript - 你如何在 Gulp 中创建一个空流?

javascript - 获取流的内容长度