我正在尝试使用
getEntityStream()
的 ContainerResponseContext
来捕获响应实体流。下面是代码:
public String getResponseEntityStream(ContainerResponseContext context) throws IOException {
OutputStream originalStream = context.getEntityStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
context.setEntityStream(baos);
String body = baos.toString();
baos.writeTo(originalStream);
baos.close();
context.setEntityStream(originalStream);
return body;
}
我在下面的代码中调用上面的方法来获取整个响应流:
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
throws IOException {
StringBuilder sbResponse = new StringBuilder();
sbResponse.append(" - Response Entity Class: ").append(responseContext.getEntityClass())
.append(System.getProperty("line.separator"));
sbResponse.append(" - Response Entity Stream: ").append(getResponseEntityStream(responseContext))
.append(System.getProperty("line.separator"));
System.out.println("HTTP RESPONSE : " + "\n" + sbResponse.toString());
}
我的问题:
在上面的代码中,
Response Entity Stream
始终为空。在我对流进行一些处理之前,我只是想读取整个响应实体流并打印它以显示原始流的样子。我在哪里犯了错误?提前致谢。
更新: 我可以使用
WriterInterceptor
获取响应正文。然而,WriterInterceptor
只有在有响应负载时才会被调用。我正在使用ContainerResponseFilter
,因为即使没有有效负载,我也想阅读响应详细信息。此外,Writer Interceptor 不能像 getStatus()
那样帮助 getStatusInfo()
和 ContainerResponseFilter
。有没有一种方法可以将 ContainerResponseFilter
和 WriterInterceptor
的数据组合在一个字符串中,并在日志中打印整个响应。可能是通过使用 Thread Local?
ContainerResponseContext
这里混淆了两种方法:
OutputStream
。该实体是在编写器拦截器阶段编写的。OutputStream
可以由用户提供的 OutputStream
进行修饰,它执行所需的操作,例如,它记录信息并将数据写入原始流。这个新的装饰器OutputStream
可以通过ContainerResponseContext#setEntityStream()注册。
Jersey 带有 LoggingFeature / ServerLoggingFilter / LoggingInterceptor。他们一起做这个日志记录,过滤器装饰原始
OutputStream
,他们记录实体、标题和其他响应相关信息。
在那些 Jersey 类中,您可以看到如何使用 ContainerRequestContext#setProperty() 和 WriterInterceptorContext#getProperty 将信息从
Filter
传递到 Interceptor
。
我认为对方法的使用存在误解
ContainerResponseContext#getEntityStream()
。一个人不应该从 OutputStream
. 阅读
正如@jan-supol 在他的回答中所说,例如,您可以用记录器装饰
OutputStream
。
但是,如果您仍想按照您的方式记录您的响应,您可以直接检索实体。
你写的代码:
OutputStream originalStream = context.getEntityStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // it's empty
context.setEntityStream(baos); // why? you're replacing the original os by this one
String body = baos.toString(); // empty stream, empty string
baos.writeTo(originalStream); // you're writing your empty stream to os, which doesn't affect the os
baos.close();
context.setEntityStream(originalStream); // assignment rollback?
return body; // returning an empty string
我会这样做的方式:
@Override
public void filter(ContainerRequestContext request, ContainerResponseContext response) {
if (response.hasEntity()) {
StringBuilder sb = new StringBuilder();
sb.append(" - Response Entity Class: ").append(response.getEntityClass())
.append(System.getProperty("line.separator"));
// in order to work, you should guarantee that entity has reasonable #toString implementation
Object entity = response.getEntity();
sb.append(" - Response Entity Stream: ").append(entity.toString())
.append(System.getProperty("line.separator"));
System.out.println("HTTP RESPONSE : " + "\n" + sb.toString());
}
}