Jasper 2 JSP 引擎操作指南
目錄
簡介
Tomcat 10.1 使用 Jasper 2 JSP 引擎來實作 JavaServer Pages 2.3 規範。
Jasper 2 經過重新設計,大幅提升效能,優於原本的 Jasper。除了改善整體程式碼外,還進行了以下變更
- JSP 自訂標籤池 - 現在可以將為 JSP 自訂標籤實例化的 Java 物件集中並重複使用。這大幅提升使用自訂標籤的 JSP 頁面效能。
- 背景 JSP 編譯 - 如果您變更已編譯的 JSP 頁面,Jasper 2 可以於背景中重新編譯該頁面。先前編譯的 JSP 頁面仍可提供服務。一旦新頁面編譯成功,就會取代舊頁面。這有助於提升 JSP 頁面在生產環境伺服器上的可用性。
- 在包含的頁面變更時重新編譯 JSP - Jasper 2 現在可以偵測到從 JSP 編譯時包含的頁面發生變更,然後重新編譯父 JSP。
- JDT 用於編譯 JSP 頁面 - Eclipse JDT Java 編譯器現在用於執行 JSP Java 原始碼編譯。此編譯器從容器類別載入器載入原始碼相依性。仍可使用 Ant 和 javac。
Jasper 使用 servlet 類別 org.apache.jasper.servlet.JspServlet
實作。
設定
預設情況下,Jasper 設定為在執行 Web 應用程式開發時使用。請參閱區段 生產設定,以取得有關在生產 Tomcat 伺服器上設定 Jasper 使用的資訊。
實作 Jasper 的 servlet 使用全域 $CATALINA_BASE/conf/web.xml
中的初始化參數進行設定。
- checkInterval - 如果開發為 false,且 checkInterval 大於 0,則會啟用背景編譯。checkInterval 是檢查 JSP 頁面(及其相依檔案)是否需要重新編譯的檢查間隔時間(以秒為單位)。預設為
0
秒。 - classdebuginfo - 是否應該使用除錯資訊編譯類別檔案?
true
或false
,預設為true
。 - classpath - 定義用於編譯產生之 servlet 的類別路徑。此參數僅在 ServletContext 屬性 org.apache.jasper.Constants.SERVLET_CLASSPATH 未設定時才會生效。當在 Tomcat 中使用 Jasper 時,此屬性始終會設定。預設情況下,類別路徑會根據目前的 Web 應用程式動態建立。
- compiler - Ant 應使用哪個編譯器來編譯 JSP 頁面。此處的有效值與 Ant 的 javac 工作的 compiler 屬性相同。如果未設定值,則會使用預設的 Eclipse JDT Java 編譯器,而不是使用 Ant。沒有預設值。如果設定此屬性,則應使用
setenv.[sh|bat]
將ant.jar
、ant-launcher.jar
和tools.jar
新增至CLASSPATH
環境變數。 - compilerSourceVM - 原始碼檔案與哪個 JDK 版本相容?(預設值:
11
) - compilerTargetVM - 已產生檔案相容的 JDK 版本為何?(預設值:
11
) - development - Jasper 是否用於開發模式?若為 true,則可透過 modificationTestInterval 參數指定檢查 JSP 是否有修改的頻率。
true
或false
,預設為true
。 - displaySourceFragment - 是否應在例外狀況訊息中包含原始碼片段?
true
或false
,預設為true
。 - dumpSmap - 是否應將 JSR45 除錯的 SMAP 資訊傾印至檔案?
true
或false
,預設為false
。若 suppressSmap 為 true,則為false
。 - enablePooling - 決定是否啟用標籤處理常式。這是編譯選項。它不會變更已編譯 JSP 的行為。
true
或false
,預設為true
。 - engineOptionsClass - 允許指定用於設定 Jasper 的 Options 類別。若不存在,則會使用預設的 EmbeddedServletOptions。若在 SecurityManager 下執行,則會略過此選項。
- errorOnUseBeanInvalidClassAttribute - 當 useBean 動作中 class 屬性的值不是有效的 bean 類別時,Jasper 是否應發出錯誤?
true
或false
,預設為true
。 - fork - 讓 Ant 分岔 JSP 頁面編譯,以便在 Tomcat 的獨立 JVM 中執行?
true
或false
,預設為true
。 - genStringAsCharArray - 是否應將文字字串產生為字元陣列,以在某些情況下提升效能?預設為
false
。 - javaEncoding - 用於產生 Java 原始碼檔案的 Java 檔案編碼。預設為
UTF8
。 - keepgenerated - 我們是否應保留每個頁面的已產生 Java 原始碼,而不是刪除它?
true
或false
,預設為true
。 - mappedfile - 我們是否應產生每個輸入列只有一個列印陳述式的靜態內容,以簡化除錯?
true
或false
,預設為true
。 - maxLoadedJsps - 將為 Web 應用程式載入的 JSP 的最大數量。若載入的 JSP 數量超過此數字,則會卸載最近最少使用的 JSP,以使任何時間載入的 JSP 數量不超過此限制。零或負值表示沒有限制。預設為
-1
- jspIdleTimeout - JSP 在卸載前可以閒置的秒數。零或負值表示永不卸載。預設為
-1
- modificationTestInterval - 導致 JSP(及其相關檔案)在最後一次檢查 JSP 是否有修改後的指定時間間隔(以秒為單位)內,不會被檢查是否有修改。值 0 會導致在每次存取時檢查 JSP。僅在開發模式中使用。預設為
4
秒。 - recompileOnFail - 如果 JSP 編譯失敗,是否應忽略 modificationTestInterval,而讓下次存取觸發重新編譯嘗試?僅在開發模式中使用,且預設為停用,因為編譯可能很耗費資源,並可能導致過度使用資源。
- scratchdir - 編譯 JSP 頁面時,我們應使用哪個暫存目錄?預設為目前 Web 應用程式的作業目錄。如果在 SecurityManager 下執行,則會忽略此選項。
- suppressSmap - 是否應抑制產生用於 JSR45 除錯的 SMAP 資訊?
true
或false
,預設為false
。 - trimSpaces - 是否應從輸出中移除完全由空白組成的範本文字(
true
)、用一個空白取代(single
)或不變更(false
)?或者,extended
選項會從範本文字中移除前導和尾隨空白,並將範本文字中的空白和換行符號序列壓縮成單一新行。請注意,如果 JSP 頁面或標籤檔案指定trimDirectiveWhitespaces
值為true
,則該值會優先於該頁面/標籤的此組態設定。預設為false
。 - xpoweredBy - 決定是否由產生的 servlet 加入 X-Powered-By 回應標頭。
true
或false
,預設為false
。 - strictQuoteEscaping - 當使用指令碼片段表達式作為屬性值時,是否應嚴格套用 JSP.1.6 中的引號字元跳脫規則?
true
或false
,預設為true
。 - quoteAttributeEL - 當在 JSP 頁面的屬性值中使用 EL 時,是否應將 JSP.1.6 中描述的屬性引號規則套用至表達式?
true
或false
,預設為true
。 - variableForExpressionFactory - 要用於表達式語言表達式工廠的變數名稱。如果未指定,則會使用預設值
_el_expressionfactory
。 - variableForInstanceManager - 要用於實例管理員工廠的變數名稱。如果未指定,則會使用預設值
_jsp_instancemanager
。 - poolTagsWithExtends - 預設情況下,透過頁面指令的 extends 屬性使用其自己的基本類別的 JSP 會停用標籤池,因為 Jasper 無法保證已執行必要的初始化。這可能會對效能產生負面影響。如果替代基本類別從 Servlet.init() 呼叫 _jspInit(),則將此屬性設定為
true
會使用替代基本類別啟用池。如果替代基本類別未呼叫 _jspInit() 而此屬性為true
,則嘗試使用標籤時會發生 NPE。true
或false
,預設為false
。 - strictGetProperty - 如果為
true
,則會強制執行在 JSP 2.0 和後續規格的 JSP.5.3 章節中指定的,在jsp:getProperty
動作中引用的物件必須先前「引入」到 JSP 處理器的需求。true
或false
,預設為true
。 - strictWhitespace - 如果為
false
,則會放寬屬性名稱前空白的要求,這樣一來,沒有空白就不會造成錯誤。true
或false
,預設為true
。 - jspServletBase - 從 JSP 產生的 Servlet 的基礎類別。如果未指定,則會使用
org.apache.jasper.runtime.HttpJspBase
的預設值。 - serviceMethodName - 基礎類別所呼叫的服務方法名稱。如果未指定,則會使用
_jspService
的預設值。 - servletClasspathAttribute - 提供 JSP 類別路徑的 ServletContext 屬性名稱。如果未指定,則會使用
org.apache.catalina.jsp_classpath
的預設值。 - jspPrecompilationQueryParameter - 導致 JSP 引擎僅預先產生 servlet 但不呼叫它的查詢參數名稱。如果未指定,則會使用 JSP 規格 (JSP.11.4.2) 所定義的
jsp_precompile
預設值。 - generatedJspPackageName - 編譯 JSP 的預設套件名稱。如果未指定,則會使用
org.apache.jsp
的預設值。 - generatedTagFilePackageName - 從標籤檔案產生的標籤處理常式的預設套件名稱。如果未指定,則會使用
org.apache.jsp.tag
的預設值。 - tempVariableNamePrefix - 用於產生的暫時變數名稱的前置詞。如果未指定,則會使用
_jspx_temp
的預設值。 - useInstanceManagerForTags - 如果為
true
,則會使用執行個體管理員來取得標籤處理常式執行個體。true
或false
,預設為false
。 - limitBodyContentBuffer - 如果為
true
,則任何擴充至bodyContentTagBufferSize
初始化參數值以外的標籤緩衝區都會被銷毀,並建立新的緩衝區。true
或false
,預設為false
。 - bodyContentTagBufferSize - 建立標籤緩衝區時要使用的 (字元) 大小。如果未指定,則會使用
org.apache.jasper.Constants.DEFAULT_TAG_BUFFER_SIZE
(512) 的預設值。
Eclipse JDT 中的 Java 編譯器包含在預設編譯器中。它是一個進階 Java 編譯器,它會從 Tomcat 類別載入器載入所有相依性,這將在大型安裝中編譯數十個 JAR 時提供極大的幫助。在快速伺服器上,這將允許即使是大型 JSP 頁面也能進行次秒重新編譯週期。
Apache Ant,它用於先前 Tomcat 版本中,可以使用它來取代新的編譯器,方法是按照上述說明配置編譯器屬性。
如果您需要變更應用程式的 JSP Servlet 設定,您可以透過在 /WEB-INF/web.xml
中重新定義 JSP Servlet 來覆寫預設組態。然而,如果您嘗試在另一個容器中部署應用程式,這可能會造成問題,因為 JSP Servlet 類別可能無法辨識。您可以透過使用 Tomcat 特定的 /WEB-INF/tomcat-web.xml
部署描述符來解決這個問題。格式與 /WEB-INF/web.xml
相同。它將覆寫任何預設設定,但不會覆寫 /WEB-INF/web.xml
中的設定。由於它是 Tomcat 特定的,因此只有在應用程式部署在 Tomcat 上時才會處理它。
已知問題
如 錯誤 39089 中所述,已知的 JVM 問題,錯誤 6294277,可能會在編譯非常大的 JSP 時造成 java.lang.InternalError: name is too long to represent
例外。如果觀察到這一點,則可以使用下列其中一項來解決
- 縮小 JSP 的大小
- 透過將
suppressSmap
設定為true
來停用 SMAP 產生和 JSR-045 支援。
生產環境設定
可以執行的主要 JSP 最佳化是 JSP 的預編譯。然而,這可能無法執行(例如,在使用 jsp-property-group 功能時)或不切實際,在這種情況下,Jasper servlet 的組態變得至關重要。
在生產 Tomcat 伺服器中使用 Jasper 2 時,您應該考慮從預設組態中進行下列變更。
- 開發 - 若要停用對 JSP 頁面編譯的存取檢查,請將其設定為
false
。 - genStringAsCharArray - 若要產生效率稍高的字元陣列,請將此設定為
true
。 - modificationTestInterval - 如果開發必須設定為
true
(例如動態產生 JSP),將此設定為高值將大幅改善效能。 - trimSpaces - 若要從回應中移除不必要的位元組,請考慮將此設定為
single
或extended
。
Web 應用程式編譯
使用 Ant 是使用 JSPC 編譯 Web 應用程式的首選方式。請注意,在預編譯 JSP 時,只有在 suppressSmap 為 false 且 compile 為 true 的情況下,SMAP 資訊才會包含在最終類別中。使用以下指令碼(「deployer」下載中包含類似的指令碼)預編譯 Web 應用程式
<project name="Webapp Precompilation" default="all" basedir=".">
<import file="${tomcat.home}/bin/catalina-tasks.xml"/>
<target name="jspc">
<jasper
validateXml="false"
uriroot="${webapp.path}"
webXmlInclude="${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"
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>
然後,必須將預編譯期間產生的 servlet 宣告和對應新增到 Web 應用程式部署描述符。將 ${webapp.path}/WEB-INF/generated_web.xml
插入 ${webapp.path}/WEB-INF/web.xml
檔案中的正確位置。重新啟動 Web 應用程式(使用管理員),並測試它以驗證它能順利執行預編譯的 servlet。也可以在 Web 應用程式部署描述符中放置適當的代碼,以使用 Ant 過濾功能自動插入產生的 servlet 宣告和對應。這實際上是所有與 Tomcat 一起發布的 Web 應用程式在建置過程中自動編譯的方式。
在 jasper 任務中,您可以使用選項 addWebXmlMappings
自動將 ${webapp.path}/WEB-INF/generated_web.xml
與目前的 Web 應用程式部署描述符 ${webapp.path}/WEB-INF/web.xml
合併。
當您想為 JSP 使用特定版本的 Java 時,請新增 javac 編譯器任務屬性 source
和 target
,並指定適當的值。例如,16
可為 Java 16 編譯 JSP。
對於製作,您可能希望使用 debug="off"
停用偵錯資訊。
當您不希望在第一個 JSP 語法錯誤時停止 JSP 產生時,請使用 failOnError="false"
,並使用 showSuccess="true"
列印出所有成功的「JSP 轉 Java」產生。當您清除 ${webapp.path}/WEB-INF/src
中產生的 Java 原始檔和編譯 ${webapp.path}/WEB-INF/classes/org/apache/jsp
中的 JSP servlet 類別時,這有時非常有幫助。
提示
- 當您切換到另一個 Tomcat 版本時,請使用新的 Tomcat 版本重新產生和重新編譯您的 JSP。
- 使用 Servlet 內容參數停用 PageContext 池
org.apache.jasper.runtime.JspFactoryImpl.POOL_SIZE=-1
,並使用 JSP Servlet 初始化參數limitBodyContentBuffer=true
限制緩衝。請注意,從預設值變更可能會影響效能,但會因應用程式而異。
最佳化
Jasper 中提供多個擴充功能點,使用戶能夠針對其環境最佳化行為。
這些擴充功能點中,第一個是標籤外掛程式機制。這允許提供標籤處理常式的替代實作,供 Web 應用程式使用。標籤外掛程式透過位於 WEB-INF
下的 tagPlugins.xml
檔案進行註冊。Jasper 中包含一個 JSTL 的範例外掛程式。
第二個擴充功能點是表達式語言直譯器。可以透過 ServletContext
設定替代直譯器。請參閱 ELInterpreterFactory
javadoc,以取得如何設定替代 EL 直譯器的詳細資料。一個主要針對標籤設定的替代直譯器提供在 org.apache.jasper.optimizations.ELInterpreterTagSetters
。請參閱 javadoc,以取得最佳化的詳細資料,以及它們對規格相容性的影響。
也提供一個擴充功能點,用於將字串值轉換為列舉。它提供在 org.apache.jasper.optimizations.StringInterpreterEnum
。請參閱 javadoc,以取得最佳化的詳細資料,以及它們對規格相容性的影響。