繁体   English   中英

使用Tomcat / Websphere将JSP编译到字符串或内存中

[英]JSP compilation to string or in memory bytearray with Tomcat/Websphere

我正在转换为图像和PDF输出。 我需要一个由我们的应用程序JSP生成的输入HTML文档。 本质上,我需要将基于JSP的应用程序的最终输出产品呈现给String或内存,然后使用该字符串进行其他处理。

有什么方法可以调用JSP渲染器来获取通常输出给用户的最终HTML内容? 理想情况下,我正在寻找适用于websphere等多个应用服务器的东西。 但是特定于Tomcat的东西也会起作用。

还有其他几种不同的方法,但我认为渲染JSP(可能包括子JSP)是最好的方法。

我宁愿远离的可选路径。

  1. 我可以使用Socket API对页面执行网络请求,然后读取从该特定页面呈现的最终输出。 这可能是下一个最佳选择,但我们在多个服务器和JVM上工作,针对我需要的页面会很复杂。

  2. 使用过滤器来获取最终页面输出。 这很好,但我一直遇到过滤器和非法状态异常的问题。 它似乎永远不会像我需要的那样100%工作。

看起来这应该很简单。 JSP编译器本质上只是一个用于解析输入JSP文档和子文档然后输出一些HTML内容的库。 我想通过Java代码调用该过程。 在服务器上,可能作为独立的控制台应用程序。

这是一个彻头彻尾的恼人问题,一个我不得不处理几次,一个我从来没有找到一个令人满意的解决方案。

基本问题是servlet API在这里没有帮助,所以你必须欺骗它。 我的解决方案是编写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();
// now use the data

它非常难看,但它是我发现的最佳解决方案。 如果您想知道,包装器响应必须包含原始响应,因为servlet规范说您在转发时无法替换完全不同的请求或响应对象,您必须使用它们的原件或包装版本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM