使用 Tomcat/Websphere 将 JSP 编译为字符串或内存字节数组

发布于 2024-07-29 04:00:30 字数 630 浏览 5 评论 0原文

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

有哪些方法可以调用 JSP 呈现器来获取通常输出给用户的最终 HTML 内容? 理想情况下,我正在寻找适用于多个应用程序服务器(例如 websphere)的东西。 但 Tomcat 特有的东西也可以工作。

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

我宁愿远离的可选路径。

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

  2. 使用过滤器获取最终页面输出。 这好吧,但我一直遇到过滤器和非法状态异常的问题。 它似乎永远无法 100% 地按照我需要的方式工作。

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

I am doing conversion to image and PDF output. I need an input HTML document that is generated by our application JSPs. Essentially, I need to render the final output product of a JSP based application to a String or memory and then use that string for other processing.

What are some ways that I can just invoke the JSP renderer to get the final HTML content that is normally output to the user?
Ideally, I am looking for something that will work for multiple application servers like websphere. But something that is Tomcat specific will also work.

There are a couple of other different approaches, but I think rendering the JSP (which may include sub JSPs) is the best approach.

Optional Paths that I would rather stay away from.

  1. I could perform a network request to the page using the Socket APIs and then read the final output that is rendered from that particular page. This is probably the next best option, but we work on multiple servers and JVMs, targeting the page I need would be complicated.

  2. Use a filter to get that final page output. This Ok but I have always had problems with filters and illegalstateexceptions. It never seems to work 100% the way I need to.

It seems like this should be simple. The JSP compiler is essentially just a library for parsing an input JSP document and subdocuments and then output some HTML content. I would like to invoke that process through Java code. On the server and possibly as a standalone console application.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

触ぅ动初心 2024-08-05 04:00:30

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

基本问题是 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 规范规定您在转发时不能替换完全不同的请求或响应对象,您必须使用原始响应或它们的包装版本。

This is a downright irritating problem, one I've had to handle a few times and one I've never found a satisfactory solution to.

The basic problem is that the servlet API is of no help here, so you have to trick it. My solution is to write a subclass of HttpServletResponseWrapper which override the getWriter() and getOutput() methods and captures the data into a buffer. You then forward() your request to the URI of the JSP you want to capture, substituting your wrapper response for the original response. You then extract the data from the buffer, manipulate it, and write the end result back to the original response.

Here's my code that does this:

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();
        }
    }

}

The code to use it can be something like this:

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

It's very ugly, but it's the best solution I've found. In case you're wondering, the wrapper response has to contain the original response because the servlet spec says that you cannot substitute a completely different request or response object when you forward, you have to use the originals, or wrapped versions of them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文