Jersey - 在调用context.proceed()之前获取Interceptor中OutputStream的内容 [英] Jersey - Obtain the contents of an OutputStream in an Interceptor before calling context.proceed()

查看:99
本文介绍了Jersey - 在调用context.proceed()之前获取Interceptor中OutputStream的内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Using an Interceptor in Jersey I can manipulate the Output, however, I also want to add a Header to the response which value is calculated from the result of the output.

@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并写入内容(从而使我能够用它做任何事情)我不能再设置标题。

However, the issue is that when I finally have read the entire stream, I'm unable to set the headers as when context.proceed is called and the contents written (and thus enabling me to do anything with it) I can no longer set the header.

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

My question in short: How do I capture the entire stream output as a byte[], calculate a result from the array of bytes and finally set the header in the response to the computed result? I do not want to deplete the output stream.

推荐答案

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

If you've ever worked with an AOP framework or even CDI interceptors, you'll have worked with the concept of Around-Advice or Around-Invoke, respectively. You can perform operations before and after the invocation of the advised/intercepted method. context.proceed() works the same way; it's the method invocation (or more precisely the MessageBodyWriter doing it's writing). We can perform some operations before the MessageBodyWriter does it's job, call proceed() to let the writer do it's work, then we can do some more work.

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

With that said, here are the steps you can take:


  1. 使用上下文从上下文保留旧的 OutputStream .getOutputStream()

  2. 创建 ByteArrayOutputStream 并将其设置为 OutputStream上下文 context.setOutputStream(baos)

  3. 致电上下文.proceed()。这样做有 MessageBodyWriter 写入 ByteArrayOutputStream

  4. 获取来自 ByteArrayOutputStream byte [] baos.toByteArray()

  5. 校验和 byte [] 并设置标题

  6. byte [] 到旧的 OutputStream

  7. 最后设置 OutputStream 上下文上到旧的 OutputStream

  1. Hold onto the old OutputStream from the context, with context.getOutputStream()
  2. Create a ByteArrayOutputStream and set that as the OutputStream on the context, with context.setOutputStream(baos)
  3. Call context.proceed(). What this does is have the MessageBodyWriter write to the ByteArrayOutputStream.
  4. Get the byte[] from the ByteArrayOutputStream with baos.toByteArray()
  5. Checksum the byte[] and set the header
  6. Write the byte[] to the old OutputStream.
  7. Finally set the OutputStream on the context to the old OutputStream.

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

Here's the basic implementation (tested and works as expected)

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

这篇关于Jersey - 在调用context.proceed()之前获取Interceptor中OutputStream的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆