gpt4 book ai didi

java - 带有 HttpServletResponseWrapper 的 Servlet 过滤器输出空主体 - 使用了错误的对象

转载 作者:太空宇宙 更新时间:2023-11-04 07:10:37 27 4
gpt4 key购买 nike

我尝试实现 HttpServletResponseWrapper 以便读取 servlet 响应的内容。我可以成功读取过滤器中的内容。但是从应用程序中发出的最终数据包的主体是空的(使用浏览器和 fiddler 检查)

实现

class ReadableContentHttpServletResponse extends HttpServletResponseWrapper {
private ByteArrayOutputStream outputStream;
private ServletOutputStream servletOutputStream;


public ReadableContentHttpServletResponse(HttpServletResponse response) {
super(response);
outputStream = new ByteArrayOutputStream();
servletOutputStream = new ServletOutputStream() {
private WriteListener writeListener = null;


@Override
public void write(int b) throws IOException {
outputStream.write(b);
if (writeListener != null) {
writeListener.notify();
}
}

@Override
public void setWriteListener(WriteListener writeListener) {
this.writeListener = writeListener;

}

@Override
public boolean isReady() {
//ByteArrayOutputStream.close() has not effect
return true;
}
};
}

@Override
public PrintWriter getWriter() throws IOException {
return new PrintWriter(outputStream);
}

@Override
public ServletOutputStream getOutputStream() throws IOException {
return servletOutputStream;
};

//... Getters...
}

过滤器

...
ReadableContentHttpServletResponse wrappedResponse = new ReadableContentHttpServletResponse(httpResponse);
chain.doFilter(request,wrappedResponse);
log.debug("content = " + wrappedResponse.getContent()); //working
log.debug("content = " + wrappedResponse.getContent()); //working

我尝试多次阅读 ByteArrayOutputStream是否在过滤器中(有效),但最终主体的数据包仍然是空的。我也尝试过 ByteArrayOutputStream Apache 。

请注意,只有一个过滤器,我删除了 dofilter 之后的所有内容。 .

编辑:用于生成最终数据包的流不是 ServletOutputStream wrapper 的。这是ServletOutputStream原版HttpServletResponse response .

为什么?因为包装器重载了 ServletResponse方法并给出 dofilter(..) ,它应该使用包装器返回的流。

最佳答案

容器始终使用原始 ServletResponseServletOutputStream,以便实际向客户端发送任何内容。

假设特定 FilterChain 中有三个 Filter:F1F2F3,并且 F2 希望修改链末端任何资源生成的数据。在这种情况下会发生以下事件:

  • F1doFilter() 是通过实例 R 作为 ServletResponse 参数来调用的,该参数又保存对 ServletOutputStream S 的引用。 F1 调用 FilterChain.doFilter(..., R)
  • F2doFilter() 也可通过 RS 调用。因为F2想要修改响应,所以它将R包装在例如HttpServletResponseWrapper 实现 R' 提供替代的 ServletOutputStream S'F2 调用 FilterChain.doFilter(..., R')
  • F3doFilter() 因此使用参数 R'S' 进行调用,并调用 `FilterChain.doFilter(..., R')。
  • 客户端请求所针对的资源将数据写入S'
  • F3doFilter() 返回。
  • F2 刷新S',对其内容执行某些操作,并将修改后的有效负载写入S。它确实不能这样做,除非它故意希望 F1 - 以及最终客户端 - 收到空响应。 F2 的 `doFilter() 返回。
  • F1 的 doFilter() 返回,S 的内容被写回客户端。

关于java - 带有 HttpServletResponseWrapper 的 Servlet 过滤器输出空主体 - 使用了错误的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20680730/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com