Tomcat 8.0 使用 Jasper 2 JSP 引擎去實現(xiàn) JavaServer Pages 2.3 規(guī)范。
Jasper 2 經(jīng)過了重新設計,極大改善了上一版 Jasper 的性能。除了一般性的代碼改進之外,還做出了以下改變:
Jasper 可以使用 servlet 類 org.apache.jasper.servlet.JspServlet
。
Jasper 默認就是用于開發(fā) Web 應用的。關(guān)于如何在 Tomcat 生產(chǎn)服務器中配置并使用 Jasper,可參考生產(chǎn)環(huán)境配置一節(jié)內(nèi)容。
在全局性的 $CATALINA_BASE/conf/web.xml
中使用如下初始參數(shù),來配置實現(xiàn) Jasper 的 servlet。
checkInterval 如果 development
為 false,并且checkInterval
大于 0,則開啟后臺編譯。checkInterval
參數(shù)的含義就是在檢查某個 JSP 頁面(以及從屬文件)是否需要重新編譯時,幾次檢查的間隔時間(以秒計)。默認為 0 秒。
classdebuginfo 是否應在編譯類文件時帶上調(diào)試信息?布爾值,默認為 true
。
classpath 對生成的 servlet 進行編譯時將要使用的類路徑。如果 ServletContext
屬性 org.apache.jasper.Constants.SERVLET_CLASSPATH
沒有設置。當在 Tomcat 中使用 Jasper 時,該屬性經(jīng)常設置。默認情況下,根據(jù)當前 Web 應用,動態(tài)創(chuàng)建類路徑。
compiler 應用何種編譯器 Ant 編譯 JSP 頁面。該參數(shù)的有效值與 Ant 的 javac 任務的編譯器屬性值完全相同。如果沒有設置該值,則采用默認的 Eclipse JDT Java 編譯器,而不是 Ant。該參數(shù)沒有默認值,如果該屬性被設置,則就應該使用 setenv.[sh|bat]
將 ant.jar
、ant-launcher.jar
與 tools.jar
添加到 CLASSPATH
環(huán)境變量中。
compilerSourceVM 與源文件所兼容的 JDK 版本?(默認值:1.7
)
compilerTargetVM 與生成文件所兼容的 JDK 版本?(默認值:1.7
)
development Jasper 是否被用于開發(fā)模式?如果為 true,可能通過 modificationTestInterval
參數(shù)來指定檢查 JSP 更改情況的頻率。布爾值,默認為 true
。
displaySourceFragment 異常信息是否應包含源代碼片段?布爾值,默認為 true
。
dumpSmap JSR45 調(diào)試的 SMAP 信息是否應轉(zhuǎn)儲到一個文件?布爾值,默認為 false
。如果 suppressSmap
為 true
,則該參數(shù)值為 false
。
enablePooling 是否啟用標簽處理池(tag handler pooling)?這是一個編譯選項。它不會影響已編譯的 JSP 行為。布爾值,默認為 true
。
engineOptionsClass 允許指定用來配置 Jasper 的 Options 類。如果不存在,則使用默認的 EmbeddedServletOptions。
errorOnUseBeanInvalidClassAttribute 當 useBean 行為中的類屬性值不是合法的 bean 類時,Jasper 是否彈出一個錯誤?布爾值,默認為 true
。
fork Ant 是否應該分叉(fork)編譯 JSP 頁面,以便在單獨的 JVM 中執(zhí)行編譯?布爾值,默認為 true
。
genStringAsCharArray 為了在一些情況下提高性能,是否應將文本字符串生成字符數(shù)組?默認為 false
。
ieClassId 使用 標記時,被送入 IE 瀏覽器中的類 ID 值。默認值為:clsid:8AD9C840-044E-11D1-B3E9-00805F499D93
。
javaEncoding 用于生成 Java 源文件的 Java 文件編碼。默認為 UTF-8
。
keepgenerated 對于每個頁面所生成的 Java 源代碼,應該保留還是刪除?布爾值,默認為 true
(保留)。
mappedfile 為便于調(diào)試,是否應該生成靜態(tài)內(nèi)容,每行輸入都帶有一個打印語句?布爾值,默認為 true
。
maxLoadedJsps Web 應用所能加載的 JSP 的最大數(shù)量。如果超出此數(shù)目,就卸載最近最少使用的 JSP,以防止任何時刻加載的 JSP 數(shù)目不超過此限。0 或負值代表沒有限制。默認為 -1。
jspIdleTimeout JSP 在被卸載前,處于空閑狀態(tài)的時間(以秒計)。0 或負值代表永遠不會卸載。默認為 -1
。
modificationTestInterval 自上次檢查 JSP 修改起,造成 JSP(以及從屬文件)沒有被檢查修改的指定時間間隔(以秒計)。取值為 0 時,每次訪問都會檢查 JSP 修改。只用于開發(fā)模式下。默認為 4
秒。
recompileOnFail 如果 JSP 編譯失敗,是否應該忽略 modificationTestInterval
,下一次訪問是否觸發(fā)重新編譯的嘗試?只用在開發(fā)模式下,并且默認是禁止的,因為編譯會使用大量的資源,是極其昂貴的過程。
scratchdir 編譯 JSP 頁面時應該使用的臨時目錄(scratch directory)。默認為當前 Web 應用的工作目錄。
suppressSmap 是否禁止 JSR45 調(diào)試時生成的 SMAP 信息?true
或 false
,缺省為 false
。
trimSpaces 是否應清除模板文本中行為與指令之間的的空格?默認為 false
。
false
。Eclipse JDT 的 Java 編譯器被指定為默認的編譯器。它非常先進,能夠從 Tomcat 類加載器中加載所有的依賴關(guān)系。這將非常有助于編譯帶有幾十個 JAR 文件的大型安裝。在較快的服務器上,還可能實現(xiàn)以次秒級周期對大型 JSP 頁面進行重新編譯。
通過配置上述編譯器屬性,之前版本 Tomcat 所用的 Apache Ant 可以替代新的編譯器。
bug 39089報告指出,在編譯非常大的 JSP 時,已知的 JVM 問題 bug 6294277 可能會導致出現(xiàn) java.lang.InternalError: name is too long to represent
異常。如果出現(xiàn)這一問題,可以采用下列辦法來解決:
suppressSmap
設為 true
,禁止生成 SMAP 信息與 JSR-045 支持。能做的最重要的 JSP 優(yōu)化就是對 JSP 進行預編譯。但這通常不太可能(比如說,使用 jsp-property-group 功能時)或者說不太實際,這種情況下,如何配置Jasper Servlet 就變得很關(guān)鍵了。
在生產(chǎn)級 Tomcat 服務器上使用 Jasper 2 時,應該考慮將默認配置進行如下這番修改:
false
。true
可以生成稍微更有效率的字符串數(shù)組。development
設為 true
,提高該值將大幅改善性能。true
可以去除響應中的無用字節(jié)。使用 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 應用部署描述符文件中的一個適當?shù)牧钆?,也能使?Ant 過濾功能自動插入生成的
servlet 聲明與映射。這實際上就是 Tomcat 所分配的所有 Web 應用能作為構(gòu)建進程中的一部分而自動編譯的原理。
在 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"
。對于動態(tài)應用而言,還可以使用 optimize="on"
進行編譯,注意,不用帶調(diào)試信息:debug="off"
。
當首次出現(xiàn) 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 類時。
提示:
org.apache.jasper.runtime.JspFactoryImpl.USE_POOL=false
禁用 PageContext 池化,利用 org.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER=true
限制緩存。注意,改變默認值可能會影響性能,但這種情況跟具體的應用有關(guān)。Jasper 還提供了很多擴展點,能讓用戶針對具體的環(huán)境而優(yōu)化行為。
標簽插件機制就是首先要談到的一個擴展點。對于提供給 Web 應用使用的標簽處理器而言,它能提供多種替代實現(xiàn)。標簽插件 通過位于 WEB-INF
的 tagPlugins.xml
進行注冊。Jasper 本身還包含了一個 JSTL 的范例插件。
表達式語言(EL,Expression Language)解釋器則是另外一個擴展點。通過 ServletContext
可以配置替代的 EL 解釋器??梢詤⒖?ELInterpreterFactory Java 文檔來了解如何配置替代的 EL 解釋器。
更多建議: