Tomcat 8.0 使用 Jasper 2 JSP 引擎去实现 JavaServer Pages 2.3 规范。
Jasper 2 经过了重新设计,极大改善了上一版 Jasper 的性能。除了一般性的代码改进之外,还做出了以下改变:
Jasper 默认就是用于开发 Web 应用的。关于如何在 Tomcat 生产服务器中配置并使用 Jasper,可参考生产环境配置一节内容。
在全局性的 $CATALINA_BASE/conf/web.xml 中使用如下初始参数,来配置实现 Jasper 的 servlet。
checkInterval 如果 development 为 false,并且checkInterval 大于 0,则开启后台编译。checkInterval 参数的含义就是在检查某个 JSP 页面(以及从属文件)是否需要重新编译时,几次检查的间隔时间(以秒计)。默认为 0 秒。
Eclipse JDT 的 Java 编译器被指定为默认的编译器。它非常先进,能够从 Tomcat 类加载器中加载所有的依赖关系。这将非常有助于编译带有几十个 JAR 文件的大型安装。在较快的服务器上,还可能实现以次秒级周期对大型 JSP 页面进行重新编译。
通过配置上述编译器属性,之前版本 Tomcat 所用的 Apache Ant 可以替代新的编译器。
bug 39089报告指出,在编译非常大的 JSP 时,已知的 JVM 问题 bug 6294277 可能会导致出现 java.lang.InternalError: name is too long to represent 异常。如果出现这一问题,可以采用下列办法来解决:
能做的最重要的 JSP 优化就是对 JSP 进行预编译。但这通常不太可能(比如说,使用 jsp-property-group 功能时)或者说不太实际,这种情况下,如何配置Jasper Servlet 就变得很关键了。
在生产级 Tomcat 服务器上使用 Jasper 2 时,应该考虑将默认配置进行如下这番修改:
使用 Ant 是利用 JSPC 编译 Web 应用的首选方式。注意在预编译 JSP 页面时,如果 suppressSmap 为 false,而 compile 为 true,则 SMAP 信息只能包含在最后的类中。使用下面的脚本来预编译 Web 应用(在 deployer 下载中也包含类似的脚本)。
<project name="Webapp Precompilation" default="all" basedir=".">
<import file="${tomcat.home}/bin/catalina-tasks.xml"/>
<target name="jspc">
<jasper
validateXml="false"
uriroot="${webapp.path}"
webXmlFragment="${webapp.path}/WEB-INF/generated_web.xml"
outputDir="${webapp.path}/WEB-INF/src" />
</target>
<target name="compile">
<mkdir dir="${webapp.path}/WEB-INF/classes"/>
<mkdir dir="${webapp.path}/WEB-INF/lib"/>
<javac destdir="${webapp.path}/WEB-INF/classes"
optimize="off"
debug="on" failonerror="false"
srcdir="${webapp.path}/WEB-INF/src"
excludes="**/*.smap">
<classpath>
<pathelement location="${webapp.path}/WEB-INF/classes"/>
<fileset dir="${webapp.path}/WEB-INF/lib">
<include name="*.jar"/>
</fileset>
<pathelement location="${tomcat.home}/lib"/>
<fileset dir="${tomcat.home}/lib">
<include name="*.jar"/>
</fileset>
<fileset dir="${tomcat.home}/bin">
<include name="*.jar"/>
</fileset>
</classpath>
<include name="**" />
<exclude name="tags/**" />
</javac>
</target>
<target name="all" depends="jspc,compile">
</target>
<target name="cleanup">
<delete>
<fileset dir="${webapp.path}/WEB-INF/src"/>
<fileset dir="${webapp.path}/WEB-INF/classes/org/apache/jsp"/>
</delete>
</target>
</project>
下面的代码可以用来运行该脚本(利用 Tomcat 基本路径与指向应被预编译 Web 应用的路径来取代令牌)
$ANT_HOME/bin/ant -Dtomcat.home=<$TOMCAT_HOME> -Dwebapp.path=<$WEBAPP_PATH>
然后,必须在 Web 应用部署描述符文件中添加预编译过程中生成的 servlet 的声明与映射。将 ${webapp.path}/WEB-INF/generated_web.xml 插入 ${webapp.path}/WEB-INF/web.xml 文件中合适的位置。使用 Manager 重启 Web 应用,测试应用,以便验证应用能正常使用预编译 servlet。利用Web 应用部署描述符文件中的一个适当的令牌,也能使用 Ant 过滤功能自动插入生成的 servlet 声明与映射。这实际上就是 Tomcat 所分配的所有 Web 应用能作为构建进程中的一部分而自动编译的原理。
在 Jasper 任务中,还可以使用选项 addWebXmlMappings,它可以将 ${webapp.path}/WEB-INF/web.xml 中的当前 Web 应用部署描述符文件自动与 ${webapp.path}/WEB-INF/generated_web.xml 进行合并。当你想在 JSP 页面中使用 Java 6 功能时,添加下列 javac 编译器任务属性:source="1.6" target="1.6"。对于动态应用而言,还可以使用 optimize="on" 进行编译,注意,不用带调试信息:debug="off"。
当首次出现 jsp 语法错误时,假如你不想停止 jsp 生成,可以使用 failOnError="false" 和 showSuccess="true",将所有成功生成的 jsp to java 打印出来。这种做法有时非常有用,比如当你想要在 ${webapp.path}/WEB-INF/src 中清除生成的 java 源文件以及 ${webapp.path}/WEB-INF/classes/org/apache/jsp 中的编译 jsp 的 servlet 类时。
提示:
Jasper 还提供了很多扩展点,能让用户针对具体的环境而优化行为。
标签插件机制就是首先要谈到的一个扩展点。对于提供给 Web 应用使用的标签处理器而言,它能提供多种替代实现。标签插件 通过位于 WEB-INF 的 tagPlugins.xml 进行注册。Jasper 本身还包含了一个 JSTL 的范例插件。
表达式语言(EL,Expression Language)解释器则是另外一个扩展点。通过 ServletContext 可以配置替代的 EL 解释器。可以参看 ELInterpreterFactory Java 文档来了解如何配置替代的 EL 解释器。