【问题标题】:JAX-RS: How to intercept json message body before sending in the response?JAX-RS:如何在发送响应之前拦截 json 消息体?
【发布时间】:2014-10-19 08:04:46
【问题描述】:

我正在创建一个只处理 json 的 JAX-RS Web 服务。我们使用的是 JAX-RS 2.0 和 Netbeans 8。所有 JPA 2.1 实体都有一个用于审计目的的唯一 ID。它不是主键。一个实体可能有其他关联实体的列表。我们需要确保实体和关联列表中的实体都具有相同的唯一 ID。如果存在差异,则审核失败。

我正在尝试找出处理此验证的最佳方法...

我可以尝试使用反射,但这很慢而且很麻烦...

我可以创建一个写拦截器,确定实体的类型,从中获取唯一 ID,然后扫描任何对象列表以确​​定是否存在差异。我不喜欢这个想法,因为我必须编写代码来验证模型中的每个特定实体,并在模型更改时维护此代码。

我最喜欢的选择是在返回给请求者之前拦截生成的 json。我可以简单地标记字符串并找到唯一的 id 值。如果有任何不同,我会抛出一个异常。这假设正在使用急切加载,这是我能想到的唯一缺点,因为这意味着我们必须始终返回完整的有效负载而不仅仅是实体。对于这个项目,我尝试使用写拦截器,但我发现实体还没有被序列化为 json。所以,我不知道如何在json返回给调用者之前拦截它。

非常感谢您对实现我的目标的最佳选择提出的建议。

感谢您的关注、建议和时间。

迈克

【问题讨论】:

    标签: java json jakarta-ee jax-rs


    【解决方案1】:

    WriterInterceptor 是一个不错的选择。如果您调用context.proceed(),它会序列化实体。 之后可以在context.getOutputStream()中找到结果。由于从这个 OutputStream 中读取并不容易,您可以使用 ByteArrayOutputStream 进行序列化并在之后恢复原始流:

    @Provider
    public class ResponseInterceptor implements WriterInterceptor {
    
        @Override
        public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
            OutputStream originalStream = context.getOutputStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            context.setOutputStream(baos);
            try {
                context.proceed();
            } finally {
                // search in the response, e.g.
                JsonNode response = new ObjectMapper().readTree(baos.toByteArray());
                // ...
                // write to and restore the original Stream
                baos.writeTo(originalStream);
                baos.close();
                context.setOutputStream(originalStream);
            }
        }
    
    }
    

    【讨论】:

    • 您好 le Floh,非常感谢您的回复。 :) 我在航班之间跑,所以我没有时间深入思考代码,所以如果以下问题是多余的,请原谅我。为了澄清起见,这种替代方法将要求实体被序列化两次......首先是我的扫描,然后是在离开写入拦截器之后。它是否正确?如果是这样,有没有办法避免进行两次序列化?再次感谢你的帮助!迈克
    • 实体将至少两次写入OutputStream。首先是ByteArrayOutputStream,然后是原始地址。这是必要的,因为原始 Stream 不提供读取其内容的方法。我认为影响不大,但这取决于您实体的规模。我建议只记录需要多长时间。
    • 一般来说,实体并不大,实体中的任何列表都会很短,所以我认为性能不会成为问题。今天下午我将快速编写代码并进行一些测试。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    • 2015-09-27
    • 2018-02-22
    • 1970-01-01
    • 1970-01-01
    • 2016-02-02
    • 1970-01-01
    相关资源
    最近更新 更多