Jersey - 在调用context.proceed()

时间:2015-11-04 09:59:10

标签: java jersey jersey-2.0

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

@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 [],从字节数组计算结果,最后在对计算结果的响应中设置标头?我不想耗尽输出流。

1 个答案:

答案 0 :(得分:4)

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

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

  1. 使用OutputStream
  2. 抓住context中的旧context.getOutputStream()
  3. 创建ByteArrayOutputStream并将其设置为上下文中的OutputStreamcontext.setOutputStream(baos)
  4. 致电context.proceed()。这样做是MessageBodyWriter写入ByteArrayOutputStream
  5. 使用byte[]
  6. ByteArrayOutputStream获取baos.toByteArray()
  7. 校验和byte[]并设置标题
  8. byte[]写入旧OutputStream
  9. 最后将OutputStream上的context设置为旧OutputStream
  10. 这是基本的实现(测试并按预期工作)

    @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);
            }
        }
    }