一尘不染

JSP以编程方式呈现

jsp

我需要以编程方式呈现JSP页面。据我了解,JSP应该具有一些编译器。问题是我可以在没有JspServlet和其他组件的情况下直接使用此编译器吗?我所需要的只是记录如何使用JSP编译器(例如Jasper)。

我认为,一些其他信息可以澄清情况。我不能使用标准的JspServlet。我想在编译之前以某种方式更改源JSP(精确地将两个JSP合并在一起),因此我需要一种直接使用JSP编译器从InputStream(或Reader)编译JSP结果的方法。

合并两个JSP是布局要求。您可以问:“但是为什么这个人不使用SiteMesh或类似的东西?”。JSP页面之一不是静态的。它由用户提供并存储在数据库中。我们对此JSP布局进行消毒和验证(用户只能使用标签的子集,并且它们并不是标准的,而是为它们专门创建的),缓存它们等等。但是现在我们需要一种方法来使用这些JSP页面(存储在内存中)作为用户请求的所有JSP页面的布局。


阅读 302

收藏
2020-06-08

共1个答案

一尘不染

我需要以编程方式呈现JSP页面。

到底有什么功能要求?您显然在寻找错误方向的解决方案。这是什么,您认为这是解决方案的问题/要求?我们可能会提出更好的建议。

例如,您是否仅需要其 输出 ?如果是这样,那么java.net.URLConnection就足够了。

编辑 :您编辑了问题:

我想在编译之前以某种方式更改源JSP(精确地将两个JSP合并在一起),因此我需要一种直接使用JSP编译器从InputStream(或Reader)编译JSP结果的方法。

OK,这是一个 有点 更加清晰。但是您需要什么呢?这些JSP实际代表什么?最终结果应用于什么?

例如,您是否只想将一个JSP包含在另一个JSP中?例如head.jspmain.jsp?中包含a
?如果是这样,那么<jsp:include>就足够了。或更糟糕的是,它们是否包含原始Java代码以及您想重用的某些特定代码?如果是这样,那么您应该使用普通的Java类,并在必要时使用taglib。

编辑2 :如您所评论:

但是现在我们需要一种方法来使用这些JSP页面(这些存储在内存中)作为用户请求的所有JSP页面的布局

只需将JSP文件存储在webapp的webcontent内的磁盘文件系统上(ServletContext#getRealPath()这里可能会抢救),然后将请求转发到您自己的主JSP文件,其中包括使用以下两个JSP文件:

<jsp:include page="${page1}" />
<jsp:include page="${page2}" />

编辑3 :我创建了一个SSCCE来证明其工作原理

package mypackage;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
        File root = new File(getServletContext().getRealPath("/"));

        String main = "<jsp:include page=\"${page1}\" /><jsp:include page=\"${page2}\" />";
        write(main, new File(root, "main.jsp"));

        String page1 = "<p>We are in ${data1}";
        write(page1, new File(root, "page1.jsp"));
        request.setAttribute("page1", "page1.jsp");
        request.setAttribute("data1", "first jsp");

        String page2 = "<p>We are in ${data2}";
        write(page2, new File(root, "page2.jsp"));
        request.setAttribute("page2", "page2.jsp");
        request.setAttribute("data2", "second jsp");

        request.getRequestDispatcher("main.jsp").forward(request, response);
    }

    private static void write(String content, File file) throws IOException {
        BufferedWriter writer = null;
        try {
            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
            writer.write(content);
        } finally {
            if (writer != null) try { writer.close(); } catch (IOException ignore) {}
        }
    }

}

http:// localhost:8080 / playground /
test
(或您使用的任何主机/上下文名称)上执行它,您将看到

We are in first jsp
We are in second jsp

为了提高效率,我将缓存每个资源,并利用它File#exists()来检查特定页面是否已保存在磁盘上。

2020-06-08