JSP以编程方式呈现

Den*_*nov 13 java jsp rendering servlets jstl

我需要以编程方式呈现JSP页面.据我所知,JSP应该有一些编译器.问题是我可以在没有JspServlet和其他人的情况下直接使用这个编译器吗?我需要的只是文档如何使用JSP编译器(例如,Jasper).

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

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

Bal*_*usC 8

我需要programmaticaly渲染JSP页面.

毕竟功能要求是什么?你正在寻找一个错误方向的解决方案.是什么,您认为这是解决方案的问题/要求是什么?我们可能会提出更好的建议.

例如,你需要它的输出吗?如果是这样,那么java.net.URLConnection就足够了.

编辑:您编辑了您的问题:

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

OK,这是一个有点更加清晰.但你需要什么呢?这些JSP实际代表什么?应该使用的最终结果是什么?

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

编辑2:正如您所说:

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

只需将JSP文件存储在webapp的webcontent中的磁盘文件系统中(这ServletContext#getRealPath()可能会在这里解决)并将请求转发到您自己的主JSP文件,其中包含两个JSP文件,例如:

<jsp:include page="${page1}" />
<jsp:include page="${page2}" />
Run Code Online (Sandbox Code Playgroud)

编辑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) {}
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

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

We are in first jsp
We are in second jsp
Run Code Online (Sandbox Code Playgroud)

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


Jas*_*man 5

我不完全确定这是否是您正在寻找的,但DWR框架包含一个方法WebContext.forwardToString,该方法将当前请求和假响应对象转发到URL,然后将缓冲区的内容读入内存.以下是代码示例:

StringWriter sout = new StringWriter();
StringBuffer buffer = sout.getBuffer();

HttpServletResponse realResponse = getHttpServletResponse();
HttpServletResponse fakeResponse = new SwallowingHttpServletResponse(realResponse, sout, realResponse.getCharacterEncoding());

HttpServletRequest realRequest = getHttpServletRequest();
realRequest.setAttribute(WebContext.ATTRIBUTE_DWR, Boolean.TRUE);

getServletContext().getRequestDispatcher(url).forward(realRequest, fakeResponse);

return buffer.toString();
Run Code Online (Sandbox Code Playgroud)

您可以使用它来获取jsp重新生成的结果并将它们存储在内存中.您可以从上面的链接下载源代码,了解SwallowingHttpServletResponse的工作原理.