使用Tomcat / Websphere将JSP编译为字符串或内存bytearray [英] JSP compilation to string or in memory bytearray with Tomcat/Websphere

查看:121
本文介绍了使用Tomcat / Websphere将JSP编译为字符串或内存bytearray的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在转换为图片和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,用您的包装器响应替换原始响应。然后,您从缓冲区中提取数据,对其进行操作,并将最终结果写回原始响应。



这是我执行此操作的代码:

 公共类CapturingResponseWrapper扩展了HttpServletResponseWrapper {

private final OutputStream buffer;

私人PrintWriter作家;
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);
}
返回outputStream;
}

@Override
public PrintWriter getWriter(){
if(writer == null){
writer = new PrintWriter(buffer);
}
返回作家;
}

@Override
public void flushBuffer()抛出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规范说您在转发时无法替换完全不同的请求或响应对象,您必须使用它们的原件或包装版本。 / p>

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.

解决方案

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.

这篇关于使用Tomcat / Websphere将JSP编译为字符串或内存bytearray的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆