我有时希望返回一个大的(几MB)二进制对象作为JAX-RS资源方法的响应。我知道对象的大小,我希望在响应上设置Content-Length标头,我不希望使用分块传输编码。
在Jersey 1.x中,我使用自定义的MessageBodyWriter解决了这个问题:
public class Blob {
public InputStream stream;
public long length;
}
@Provider
public class BlobWriter extends MessageBodyWriter<Blob> {
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return Blob.class.isAssignableFrom(type);
}
public long getSize(T t, Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
return t.length;
}
public void writeTo(T t, Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream)
throws java.io.IOException {
org.glassfish.jersey.message.internal.ReaderWriter.writeTo(t.stream, entityStream);
}
}
但是当我升级到Jersey 2.x时,这停止了工作,因为JAX-RS / Jersey 2不再关心MessageBodyWriter.getSize()了。我怎样才能用Jersey 2来实现这个目标?
答案 0 :(得分:4)
似乎可以使用提供的httpHeaders从MessageBodyWriter.writeTo()设置Content-Length标头:
public void writeTo(T t, Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream)
throws java.io.IOException {
httpHeaders.addFirst(HttpHeaders.CONTENT_LENGTH, t.length.toString);
org.glassfish.jersey.message.internal.ReaderWriter.writeTo(t.stream, entityStream);
}
答案 1 :(得分:3)
从JAX-RS 2.0开始,该方法已被弃用且价值不足 JAX-RS运行时忽略该方法返回的方法。所有 建议MessageBodyWriter实现从中返回-1 方法。负责计算实际的Content-Length标头 值已委托给JAX-RS运行时。
JAX-RS实施还将决定是否会发送Content-Length
标头或Transfer-Encoding: chunked
。
正如您已经了解Content-Length,您可以在ResourceClass中设置一个临时标题,并在ContainerResponseFilter中设置真实标题:
@Path("/foo")
public class SomeResource {
@GET
public Blob test() {
return Response.ok(...).header("X-Content-Length", blob.length()).build();
}
}
@Provider
public class HeaderFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
String contentLength = responseContext.getHeaderString("X-Content-Length");
if (contentLength != null) {
responseContext.getHeaders().remove("Transfer-Encoding");
responseContext.getHeaders().remove("X-Content-Length");
responseContext.getHeaders().putSingle("Content-Length", contentLength);
}
}
}