如何在启动时使Tomcat预编译JSP?

我正在使用Apache Tomcat 6.0和Jetty 6。 我们主要使用Jetty进行测试(它非常适合在JUnit测试中运行嵌入式)和Tomcat用于生产。

默认情况下,Tomcat会在用户请求时动态编译JSP。 但这会导致第一次打击的性能下降。 它还突出了Tomcat的JSP编译器中的奇怪错误 。

Tomcat文档提供了在构建时使用Ant预编译JSP的建议(并且还提供了Maven插件)……但是生成的WAR包含特定于Tomcat的东西,例如PageContextImpl.proprietaryEvaluate,因此我们不能在Jetty中使用它。

是否有一些标志或设置我们可以使用某个地方强制Tomcat在WAR初始化后立即预编译所有JSP? 我们准备在启动时等待一段时间。

事先:我知道有一种方法可以通过在web.xml中为一个JSP显式标识/ servlet / load-on-startup标记来预编译一个JSP。 但对于数十甚至数百个难以管理的JSP而言。

http://www.devshed.com/c/a/BrainDump/Tomcat-Capacity-Planning/


project name="pre-compile-jsps" default="compile-jsp-servlets">                                                                 

此构建文件将查找所有webapp的JSP文件,将它们编译为servlet类,并为这些JSP servlet类生成servlet映射。 它生成的servlet map ping必须进入你的webapp的WEB-INF / web.xml文件,但是编写一个知道如何以可重复的方式将servlet映射插入web.xml文件的Ant构建文件是很困难的。构建文件运行的时间。 相反,我们使用XML实体包含,以便每次构建文件运行时生成的servlet映射都会进入新文件,并且可以通过XML实体包含机制将servlet映射文件插入到web.xml文件中。 要使用它,您的webapp的WEB-INF / web.xml必须在文件顶部有一个特殊的实体声明,以及您希望servlet映射文件在web.xml文件内容中的实体的引用包括在内。 以下是一个空的servlet 2.5 webapp的web.xml文件如何看待这些修改:

  ]>   &jspc-webxml;   

确保您的webapp的web.xml文件在文件顶部和下面的servlet 2.5 web-app模式声明中一直有内联DTD(DOCTYPE标记)。 然后,无论您希望在web.xml文件中插入生成的servlet映射,请将实体引用&jspc-webxml; 。 请记住,实体引用以和号(&)开头,然后具有实体的名称,并以分号(;)结尾。

要使用构建文件,只需编辑它并将顶部的所有属性设置为与您的设置匹配的值,然后像下面这样运行:

$ ant -f pre-compile-jsps.xml

如果你选择duffymo提到的解决方案指向Vinny Carpenter的博客,我有一个提示。 有一个区域导致我的容器在联系localhost时无限期挂起(特别是在private connect()方法中)。 使用以下hack是我的解决方法:

  private void connect(final String urlString) { HttpURLConnection conn; try { final URL url = new URL(urlString); conn = (HttpURLConnection)url.openConnection(); conn.setConnectTimeout(5000); //time it out quickly - otherwise hangs forever //seems to be an issue hitting localhost //will still precompile the page conn.setReadTimeout(100); conn.setAllowUserInteraction(true); conn.getInputStream(); conn.disconnect(); } catch (SocketTimeoutException e) { log.debug(e); } catch (IOException ioe) { log.error(ioe); } } 

设置超时并忽略SocketTimeoutException工作(虽然无可否认不是最佳解决方案)。 此外,使用此过程意味着您需要在web.xml中指定JSP。 这足以满足我的需求。