这是一个完全令人恼火的问题,一个我不得不处理几次,一个我从来没有找到满意的解决办法。
最基本的问题是ServletAPI在这里没有帮助,所以您必须欺骗它。我的解决方案是编写HttpServletResponseWrapper的子类,该子类重写getWriter()和getOutput()方法并将数据捕获到缓冲区中。然后将请求转发到要捕获的JSP的URI,用包装器响应替换原始响应。然后从缓冲区提取数据,对其进行操作,并将最终结果写回原始响应。
这是我的代码:
public class CapturingResponseWrapper extends HttpServletResponseWrapper {
private final OutputStream buffer;
private PrintWriter writer;
private ServletOutputStream outputStream;
public CapturingResponseWrapper(HttpServletResponse response, OutputStream buffer) {
super(response);
this.buffer = buffer;
}
@Override
public ServletOutputStream getOutputStream() {
if (outputStream == null) {
outputStream = new DelegatingServletOutputStream(buffer);
}
return outputStream;
}
@Override
public PrintWriter getWriter() {
if (writer == null) {
writer = new PrintWriter(buffer);
}
return writer;
}
@Override
public void flushBuffer() throws IOException {
if (writer != null) {
writer.flush();
}
if (outputStream != null) {
outputStream.flush();
}
}
}
使用它的代码可以是这样的:
HttpServletRequest originalRequest = ...
HttpServletResponse originalResponse = ...
ByteArrayOutputStream bufferStream = new ByteArrayOutputStream();
CapturingResponseWrapper responseWrapper = new CapturingResponseWrapper(originalResponse, bufferStream);
originalRequest.getRequestDispatcher("/my.jsp").forward(originalRequest, responseWrapper);
responseWrapper.flushBuffer();
byte[] buffer = bufferStream.toByteArray();
很难看,但这是我找到的最好的解决办法。如果您想知道,包装器响应必须包含原始响应,因为servlet规范指出,转发时不能替换完全不同的请求或响应对象,您必须使用它们的原始版本或包装版本。