【问题标题】:Jersey - Obtain the contents of an OutputStream in an Interceptor before calling context.proceed()Jersey - 在调用 context.proceed() 之前在 Interceptor 中获取 OutputStream 的内容
【发布时间】:2015-11-04 09:59:10
【问题描述】:

在 Jersey 中使用拦截器我可以操纵输出,但是,我还想在响应中添加一个标头,其值是根据输出结果计算得出的。

@Sha256Sum
public class Sha256SumInterceptor implements WriterInterceptor {

    public static final String SHA256_HASH_HEADER_NAME = "SHA256-SUM";

    @Override
    public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
        // Retrieve the OutputStream, read the contents and calculate the hashsum.
        // Set the header value in context.
        context.proceed();
    }
}

但是,问题在于,当我最终阅读了整个流时,我无法将标题设置为调用 context.proceed 并写入内容(从而使我能够对它做任何事情)我可以不再设置标题。

简而言之,我的问题是:如何将整个流输出捕获为 byte[],从字节数组计算结果,最后在对计算结果的响应中设置标头?我不想耗尽输出流。

【问题讨论】:

    标签: java jersey jersey-2.0


    【解决方案1】:

    如果您曾经使用过 AOP 框架甚至 CDI 拦截器,那么您将分别使用过 Around-Advice 或 Around-Invoke 的概念。您可以在调用建议/拦截方法之后在 之前执行操作。 context.proceed() 工作方式相同;这是方法调用(或更准确地说是MessageBodyWriter 正在编写)。我们可以在MessageBodyWriter 完成它的工作之前执行一些操作,调用proceed() 让作者完成它的工作,然后我们可以做更多的工作。

    话虽如此,您可以采取以下步骤:

    1. context 保留旧的OutputStream,与context.getOutputStream()
    2. 创建一个ByteArrayOutputStream 并将其设置为上下文中的OutputStream,使用context.setOutputStream(baos)
    3. 致电context.proceed()。这样做是让MessageBodyWriter 写入ByteArrayOutputStream
    4. ByteArrayOutputStreambaos.toByteArray() 获取byte[]
    5. 校验和byte[]并设置标题
    6. byte[] 写入旧的OutputStream
    7. 最后将context上的OutputStream设置为旧的OutputStream

    这是基本实现(经过测试并按预期工作)

    @Provider
    public class ChecksumInterceptor implements WriterInterceptor {
    
        @Override
        public void aroundWriteTo(WriterInterceptorContext context)
                throws IOException, WebApplicationException {
    
            OutputStream old = context.getOutputStream();
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            try {
    
                context.setOutputStream(buffer);
                // let MessageBodyWriter do it's job
                context.proceed();
    
                // get bytes
                byte[] entity = buffer.toByteArray();
    
                String checksum = ChecksumUtil.createChecksum(entity);
                context.getHeaders().putSingle("X-Checksum", checksum);
    
                old.write(entity);
            } finally {
                context.setOutputStream(old);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-24
      • 1970-01-01
      • 1970-01-01
      • 2012-02-05
      • 1970-01-01
      相关资源
      最近更新 更多