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を再コンパイルできるようになりました。
  • JSPページのコンパイルにJDTを使用 - Eclipse JDT JavaコンパイラがJSP Javaソースコードのコンパイルに使用されるようになりました。このコンパイラは、コンテナクラスローダーからソースの依存関係を読み込みます。Antとjavacを引き続き使用できます。

Jasperは、サーブレットクラスorg.apache.jasper.servlet.JspServletを使用して実装されています。

設定

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

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

  • checkInterval - developmentがfalseでcheckIntervalがゼロより大きい場合、バックグラウンドコンパイルが有効になります。 checkIntervalは、JSPページ(およびその依存ファイル)を再コンパイルする必要があるかどうかを確認する間隔(秒単位)です。デフォルトは0秒です。
  • classdebuginfo - クラスファイルをデバッグ情報付きでコンパイルする必要がありますか? trueまたはfalse、デフォルトはtrueです。
  • classpath - 生成されたサーブレットのコンパイルに使用されるクラスパスを定義します。このパラメータは、ServletContext属性org.apache.jasper.Constants.SERVLET_CLASSPATHが設定されていない場合にのみ有効です。この属性は、Tomcat内でJasperが使用される場合は常に設定されます。デフォルトでは、クラスパスは現在のWebアプリケーションに基づいて動的に作成されます。
  • compiler - AntがJSPページのコンパイルに使用するコンパイラ。この有効な値は、Antのjavacタスクのcompiler属性と同じです。値が設定されていない場合、Antを使用する代わりに、デフォルトのEclipse JDT Javaコンパイラが使用されます。デフォルト値はありません。この属性を設定する場合は、setenv.[sh|bat]を使用して、ant.jarant-launcher.jar、およびtools.jarCLASSPATH環境変数に追加する必要があります。
  • compilerSourceVM - ソースファイルと互換性のあるJDKバージョンはどれですか? (デフォルト値:11
  • compilerTargetVM - 生成されたファイルと互換性のあるJDKバージョンはどれですか? (デフォルト値:11
  • 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が使用されます。 SecurityManagerで実行している場合、このオプションは無視されます。
  • errorOnUseBeanInvalidClassAttribute - useBeanアクションのclass属性の値が有効なBeanクラスでない場合、Jasperはエラーを発行する必要がありますか? trueまたはfalse、デフォルトはtrueです。
  • fork - AntはJSPページのコンパイルをフォークして、Tomcatとは別のJVMで実行する必要がありますか? trueまたはfalse、デフォルトは`true`です。
  • genStringAsCharArray - 一部のケースでパフォーマンスを向上させるために、テキスト文字列をchar配列として生成する必要がありますか? デフォルトは`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が最後に変更 checkedされてから指定された時間間隔(秒単位)の間、JSP(およびその依存ファイル)が変更 checkedされないようにします。値0は、アクセスごとにJSPが checkedされることを示します。開発モードでのみ使用されます。デフォルトは`4`秒です。
  • recompileOnFail - JSPのコンパイルが失敗した場合、modificationTestIntervalを無視して、次のアクセスで再コンパイルを試みる必要がありますか?開発モードでのみ使用され、デフォルトでは無効になっています。コンパイルにはコストがかかり、リソースを過剰に使用してしまう可能性があるためです。
  • scratchdir - JSPページのコンパイル時に使用するスクラッチディレクトリは何ですか?デフォルトは、現在のWebアプリケーションの作業ディレクトリです。 SecurityManagerで実行している場合、このオプションは無視されます。
  • 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 - JSPページの属性値にELが使用される場合、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 2.0以降の仕様のJSP.5.3章で指定されているように、jsp:getPropertyアクションで参照されるオブジェクトが、以前に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コンパイラは、デフォルトのコンパイラとして含まれています。これは、Tomcatクラスローダーからすべての依存関係を読み込む高度なJavaコンパイラであり、数十個のJARを含む大規模なインストールでコンパイルする場合に非常に役立ちます。高速サーバーでは、大きなJSPページでも1秒未満の再コンパイルサイクルが可能になります。

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

アプリケーションの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 - 少し効率的なchar配列を生成するには、これをtrueに設定します。
  • modificationTestInterval - 何らかの理由(JSPの動的生成など)でdevelopmentをtrueに設定する必要がある場合、これを高い値に設定するとパフォーマンスが大幅に向上します。
  • trimSpaces - レスポンスから不要なバイトを削除するには、これをsingleまたはextendedに設定することを検討してください。

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

Antを使用するのが、JSPCを使用してWebアプリケーションをコンパイルするための推奨される方法です。JSPをプリコンパイルする場合、SMAP情報はsuppressSmapがfalseでcompileがtrueの場合にのみ最終クラスに含まれることに注意してください。以下のスクリプト(同様のスクリプトが「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${webapp.path}/WEB-INF/web.xmlにある現在のWebアプリケーションデプロイメント記述子と自動的にマージできます。

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

本番環境では、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サーブレットクラスをクリーンアップする場合に非常に役立ちます。

ヒント

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

最適化

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

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

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

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