Jasper 2 JSPエンジン 使い方

目次

はじめに

Tomcat 11.0は、Jasper 2 JSPエンジンを使用して、Jakarta Pages 4.0仕様を実装しています。

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は、サーブレットクラスorg.apache.jasper.servlet.JspServletを使用して実装されています。

設定

デフォルトでは、JasperはWebアプリケーションの開発を行う際に使用するように設定されています。本番Tomcatサーバーで使用するためにJasperを設定する方法については、本番環境の設定セクションを参照してください。

Jasperを実装するサーブレットは、グローバルの$CATALINA_BASE/conf/web.xmlの初期化パラメータを使用して設定されます。

  • checkInterval - developmentがfalseで、checkIntervalがゼロより大きい場合、バックグラウンドコンパイルが有効になります。checkIntervalは、JSPページ(およびその依存ファイル)を再コンパイルする必要があるかどうかを確認する間隔(秒単位)です。デフォルトは0秒です。
  • classdebuginfo - クラスファイルはデバッグ情報付きでコンパイルする必要がありますか?trueまたはfalse、デフォルトはtrue
  • classpath - 生成されたサーブレットをコンパイルするために使用されるクラスパスを定義します。このパラメータは、ServletContext属性org.apache.jasper.Constants.SERVLET_CLASSPATHが設定されていない場合にのみ有効です。この属性は、JasperがTomcat内で使用される場合は常に設定されます。デフォルトでは、クラスパスは現在のWebアプリケーションに基づいて動的に作成されます。
  • compiler - JSPページのコンパイルにAntが使用するコンパイラを指定します。有効な値は、Antのjavacタスクのcompiler属性と同じです。値が設定されていない場合、Antを使用する代わりに、デフォルトのEclipse JDT Javaコンパイラが使用されます。デフォルト値はありません。この属性が設定されている場合は、setenv.[sh|bat]を使用して、ant.jarant-launcher.jar、およびtools.jarCLASSPATH環境変数に追加する必要があります。
  • compilerSourceVM - ソースファイルと互換性のあるJDKバージョンは何ですか? (デフォルト値: 17)
  • compilerTargetVM - 生成されたファイルと互換性のあるJDKバージョンは何ですか? (デフォルト値: 17)
  • development - Jasperは開発モードで使用されていますか? trueの場合、JSPが変更されているかどうかを確認する頻度は、modificationTestIntervalパラメータで指定できます。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が使用されます。
  • 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 - デバッグを容易にするために、入力行ごとに1つのprintステートメントを持つ静的コンテンツを生成する必要がありますか?trueまたはfalse、デフォルトはtrue
  • maxLoadedJsps - WebアプリケーションにロードされるJSPの最大数。この数を超えるJSPがロードされると、ロードされているJSPの数がこの制限を超えないように、最も最近使用されていないJSPがアンロードされます。ゼロ以下の値は、制限がないことを示します。デフォルトは-1
  • jspIdleTimeout - JSPがアンロードされるまでにアイドル状態にできる時間(秒単位)。ゼロ以下の値は、決してアンロードしないことを示します。デフォルトは-1
  • modificationTestInterval - JSP(およびその依存ファイル)が、最後に変更を確認した時点から指定された時間間隔(秒単位)の間、変更を確認されないようにします。値が0の場合、アクセスごとにJSPが確認されます。開発モードでのみ使用されます。デフォルトは4秒です。
  • recompileOnFail - JSPのコンパイルが失敗した場合、modificationTestIntervalを無視して、次のアクセスで再コンパイルをトリガーする必要がありますか?開発モードでのみ使用され、コンパイルにコストがかかり、過度のリソース使用につながる可能性があるため、デフォルトでは無効になっています。
  • scratchdir - JSPページのコンパイル時に使用するスクラッチディレクトリは何ですか?デフォルトは、現在のWebアプリケーションの作業ディレクトリです。
  • suppressSmap - JSR45デバッグ用のSMAP情報の生成を抑制する必要がありますか?trueまたはfalse、デフォルトはfalse
  • trimSpaces - 空白文字のみで構成されるテンプレートテキストを、出力から削除する (true)、単一のスペースに置き換える (single)、または変更しない (false) のどれにする必要がありますか? または、extended オプションを使用すると、テンプレートテキストの先頭と末尾の空白文字が削除され、テンプレートテキスト内の連続する空白文字と改行が単一の改行に折りたたまれます。 JSP ページまたはタグファイルで trimDirectiveWhitespaces の値を true に指定した場合、そのページ/タグではこの設定よりも優先されることに注意してください。 デフォルトは false です。
  • xpoweredBy - 生成されたサーブレットによってX-Powered-Byレスポンスヘッダーが追加されるかどうかを決定します。trueまたはfalse、デフォルトはfalse
  • strictQuoteEscaping - スクリプトレット式が属性値に使用されている場合、引用符のエスケープに関するJSP.1.6のルールを厳密に適用する必要がありますか?trueまたはfalse、デフォルトはtrue
  • quoteAttributeEL - ELがJSPページの属性値で使用されている場合、JSP.1.6で説明されている属性の引用符付けのルールを式に適用する必要がありますか?trueまたはfalse、デフォルトはtrue
  • variableForExpressionFactory - 式言語の式ファクトリに使用する変数の名前。指定しない場合、デフォルト値の_el_expressionfactoryが使用されます。
  • variableForInstanceManager - インスタンスマネージャーファクトリに使用する変数の名前。指定しない場合、デフォルト値の_jsp_instancemanagerが使用されます。
  • poolTagsWithExtends - デフォルトでは、pageディレクティブのextends属性を介して独自のベースクラスを使用するJSPは、必要な初期化が行われたことをJasperが保証できないため、タグのプーリングが無効になります。これにより、パフォーマンスに悪影響を与える可能性があります。代替のベースクラスがServlet.init()から_jspInit()を呼び出す場合、このプロパティをtrueに設定すると、代替のベースクラスでのプーリングが有効になります。代替のベースクラスが_jspInit()を呼び出さず、このプロパティがtrueの場合、タグを使用しようとするとNPEが発生します。trueまたはfalse、デフォルトはfalse
  • strictGetProperty - trueの場合、jsp:getPropertyアクションで参照されるオブジェクトが、JSP 2.0以降の仕様のJSP.5.3章で指定されているように、事前にJSPプロセッサに「導入」されていることが要求されます。trueまたはfalse、デフォルトはtrue
  • strictWhitespace - falseの場合、属性名の前の空白文字の要件が緩和され、空白文字がないことがエラーの原因にはなりません。trueまたはfalse、デフォルトはtrue
  • jspServletBase - JSPから生成されたサーブレットのベースクラス。指定しない場合、デフォルト値のorg.apache.jasper.runtime.HttpJspBaseが使用されます。
  • serviceMethodName - ベースクラスによって呼び出されるサービスメソッドの名前。指定しない場合、デフォルト値の_jspServiceが使用されます。
  • servletClasspathAttribute - JSPのクラスパスを提供するServletContext属性の名前。指定しない場合、デフォルト値のorg.apache.catalina.jsp_classpathが使用されます。
  • jspPrecompilationQueryParameter - JSPエンジンにサーブレットを事前生成するだけで、呼び出さないようにするクエリパラメータの名前。指定しない場合、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ページでも1秒未満の再コンパイルサイクルが可能になります。

以前のTomcatリリースで使用されていたApache Antは、上記のコンパイラ属性を構成することにより、新しいコンパイラの代わりに使用できます。

アプリケーションのJSPサーブレットの設定を変更する必要がある場合は、/WEB-INF/web.xmlでJSPサーブレットを再定義して、デフォルト構成をオーバーライドできます。ただし、JSPサーブレットクラスが認識されない可能性があるため、別のコンテナにアプリケーションをデプロイしようとすると、問題が発生する可能性があります。この問題を回避するには、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のサイズを縮小する
  • suppressSmaptrueに設定して、SMAPの生成とJSR-045のサポートを無効にする。

本番環境の設定

実行できる主なJSPの最適化は、JSPの事前コンパイルです。ただし、jsp-property-group機能を使用している場合など、これが不可能または実用的でない場合は、Jasperサーブレットの構成が重要になります。

本番TomcatサーバーでJasper 2を使用する場合は、デフォルト構成から次の変更を行うことを検討する必要があります。

  • development - JSPページのコンパイルへのアクセスチェックを無効にするには、これをfalseに設定します。
  • genStringAsCharArray - わずかに効率的な文字配列を生成するには、これをtrueに設定します。
  • modificationTestInterval - JSPの動的な生成など、何らかの理由でdevelopmentをtrueに設定する必要がある場合は、これを高い値に設定すると、パフォーマンスが大幅に向上します。
  • trimSpaces - レスポンスから不要なバイトを削除するには、これをsingleまたはextendedに設定することを検討してください。

Webアプリケーションのコンパイル

JSPCを使用したWebアプリケーションのコンパイルには、Antを使用することをお勧めします。 JSPsを事前にコンパイルする場合、suppressSmapがfalseで、compileがtrueの場合にのみ、SMAP情報が最終クラスに含まれることに注意してください。 次に示すスクリプト(同様のスクリプトは「deployer」ダウンロードに含まれています)を使用して、webappを事前にコンパイルします

<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ベースパスと、事前にコンパイルする必要があるwebappへのパスに置き換えます)

$ANT_HOME/bin/ant -Dtomcat.home=<$TOMCAT_HOME> -Dwebapp.path=<$WEBAPP_PATH>

次に、事前コンパイル中に生成されたサーブレットの宣言とマッピングを、Webアプリケーションのデプロイメント記述子に追加する必要があります。 ${webapp.path}/WEB-INF/generated_web.xml${webapp.path}/WEB-INF/web.xmlファイルの適切な場所に挿入します。(マネージャーを使用して)Webアプリケーションを再起動し、事前コンパイルされたサーブレットで正常に実行されていることを確認するためにテストします。 Webアプリケーションのデプロイメント記述子に配置された適切なトークンを使用して、Antフィルタリング機能を使用して生成されたサーブレットの宣言とマッピングを自動的に挿入することもできます。 これは、Tomcatで配布されるすべてのWebappがビルドプロセスの一部として自動的にコンパイルされる方法です。

jasperタスクでは、addWebXmlMappingsオプションを使用して、${webapp.path}/WEB-INF/generated_web.xmlを現在のWebアプリケーションのデプロイメント記述子と${webapp.path}/WEB-INF/web.xmlで自動的にマージできます。

JSPに特定のバージョンのJavaを使用する場合は、javacコンパイラタスク属性sourceおよびtargetを適切な値で追加します。 たとえば、Java 16用にJSPをコンパイルするには16です。

本番環境では、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サーブレットクラスをコンパイルすると非常に役立つ場合があります。

ヒント

  • 別のTomcatリリースに切り替える場合は、新しいTomcatバージョンでJSPを再生成して再コンパイルします。
  • Servletコンテキストパラメーターを使用してPageContextプーリングorg.apache.jasper.runtime.JspFactoryImpl.POOL_SIZE=-1を無効にし、JSPサーブレット初期化パラメーターlimitBodyContentBuffer=trueでバッファリングを制限します。 デフォルトからの変更はパフォーマンスに影響を与える可能性がありますが、アプリケーションによって異なることに注意してください。

最適化

Jasperには、ユーザーが環境に合わせて動作を最適化できる拡張ポイントが多数用意されています。

これらの拡張ポイントの1つは、タグプラグインメカニズムです。 これにより、Webアプリケーションが使用するタグハンドラーの代替実装を提供できます。 タグプラグインは、WEB-INFにあるtagPlugins.xmlファイルを介して登録されます。 JSTLのサンプルプラグインがJasperに含まれています。

2番目の拡張ポイントは、Expression Languageインタープリターです。 代替インタープリターは、ServletContextを通じて構成できます。 代替ELインタープリターの構成方法の詳細については、ELInterpreterFactory javadocを参照してください。 タグ設定を主にターゲットとする代替インタープリターは、org.apache.jasper.optimizations.ELInterpreterTagSettersで提供されます。 最適化と仕様コンプライアンスへの影響の詳細については、javadocを参照してください。

String値をEnumに強制変換するための拡張ポイントも提供されています。 これはorg.apache.jasper.optimizations.StringInterpreterEnumで提供されています。 最適化と仕様コンプライアンスへの影響の詳細については、javadocを参照してください。