2009-11-12 58 views
11

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

我想,一些额外的信息将阐明情况。我不能使用标准的JspServlet。我想在编译之前以某种方式更改源JSP(精确地将两个JSP合并在一起),所以我需要一种方法来直接使用JSP编译器从InputStream(或Reader)编译JSP结果。

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

+1

我有一个类似的问题,我发现“最简单”的解决方案是将整个项目切换到Velocity(或其他模板引擎),在这些任务是微不足道的。看起来你在开发过程中已经太过于做出这样的改变,但只是说... – serg 2009-11-12 02:25:33

回答

8

我需要programmaticaly渲染的JSP页面。

究竟是什么功能要求?你显然在找错方向的解决方案。它是什么,你认为这是解决方案的问题/要求?我们可能会提出更好的建议。

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

编辑:您编辑您的问题:

我想在编译之前修改源JSP以某种方式(合并两个JSP在一起,要准确),所以我需要一种方法来编译JSP结果从InputStream(或Reader)直接使用JSP Compiller。

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

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

编辑2:当你说:

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

只存储web应用程序的web内容的内部磁盘文件系统上的JSP文件(ServletContext#getRealPath()可能会进入救援在这里),并转发给自己的主JSP文件的请求使用的考试,其中包括两个JSP文件PLE:

<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(或者你使用任何主机/ CONTEXTNAME)执行它,你会看到

We are in first jsp 
We are in second jsp 

为了更高效的I能缓存一切资源和利用File#exists()到检查特定页面是否已经保存在磁盘上。

+0

好吧,让我们深入了解需求。两个JSP的合并是布局要求。你可以问:“但为什么这个人只是不使用SiteMesh或类似的东西?”。其中一个JSP页面不是静态的。它由用户提供并存储在数据库中。我们对这个JSP布局进行了清理和验证(用户只能使用标签的子集,并且它们都不是标准的,而是专门为它们创建的),缓存它们等等。但是现在我们需要一种方法来将这些JSP页面(即存储在内存中的页面)用作用户请求的所有JSP页面的布局。 – 2009-11-12 02:08:47

+0

好吧,它会工作。但是我希望我的JSP看起来更干净一些。像 ...和页面标签的子页面描述页面。自身的页面标签取代了编译时的布局。这在某种程度上可能吗? – 2009-11-12 02:24:08

+0

只需在JSP内容的顶部包含taglibs即可。只需按照常规方式编写JSP代码。所有你需要做的就是将它存储在webapp的webcontent中。查看我上次添加的SSCCE。 – BalusC 2009-11-12 02:34:50

1

也许你可以使用Tomcat's JspC ant task

+0

不完全。我需要自己编译服务器端的JSP。所以蚂蚁的任务不是我想要的。但我会看看这个任务的源代码。也许这将是有益的。谢谢。 – 2009-11-12 01:39:35

1

JSTL只是JSP文件中使用的标签库。所以在这方面真的没关系。由于JSP编译器将JSP文件转换为Java Servlet,我怀疑你可以让它直接运行(编译器实际上不会运行任何东西!),或者为此提供一个JSP文件。

实际上很难从你的问题中理解你真正需要的东西。

编辑:我会建议JSP:包括作业

+0

是的,在这方面提及JSTL是不方便的,同意。 而你说得对,JSP页面在编译之后变成了servlet。我需要的是一种自己编译JSP页面到servlet的方法。我可以更深入地解释我的任务。我需要以某种方式(从源代码)合并两个JSP文件,然后编译结果。 – 2009-11-12 01:51:31

+0

将其中一个JSP文件包含在其他文件中是不够的?参见jsp:include和<%@include%> – 2009-11-12 01:59:02

+0

不幸的是,没有。 JSP合并的规则不是微不足道的。这是自己的问题,但... – 2009-11-12 02:01:53

1

如果JSP已经被appserver预编译,那么您可以查找生成的.class文件。在Tomcat中,这应该在$ CONTEXT_ROOT/org/apache/jsp /目录下。你可能能够以某种方式运行这个类并生成你的输出。

编辑:错过了关于修改JSP源代码的编辑。

看看org.apache.jasper.compiler.AntCompiler(包含在Tomcat的jasper.jar中)。有一种名为generateClass的受保护方法,您可能可以覆盖并篡改:)

1

您需要这样做的原因是什么? 如果您需要合并2个jsp文件进行处理,也许使用包括 或者您需要其他想法?你可以提供关于你的请求的样本吗?

4

我不完全确定这是否是您要查找的内容,但DWR framework包含一个称为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(); 

您可以使用它来获得JSP rednering的结果,并将其存储在内存中。你可以从上面的链接下载源代码,看看SwallowingHttpServletResponse是如何工作的。

相关问题