長年Tomcatを使っていますが、(ふとしたことから)web.xml
の中でプレースホルダ(${...}
)が使えることを初めて知りました。
(Tomcat固有の設定ファイル(server.xml
やcontext.xml
)で使えるのは知っていましたが・・・)
Important:
念のため・・プレースホルダは、Servlet APIの仕様ではありませんので、勘違いしないように!!
とりあえずプレースホルダを使ってみる
ここでは、セッションタイムアウト時間をプレースホルダ化しておき、システムプロパティから実際の値を取得してみます。
<session-config>
<session-timeout>${session.timeout}</session-timeout>
<!-- ... -->
</session-config>
Tomcat起動時のVM引数として「-Dsession.timeout=1
」を指定すると、セッションタイムアウト時間が1分になります。
でも・・・デフォルト値の指定はできない
Tomcatが提供しているデフォルト実装では、プレースホルダの中にデフォルト値(プロパティ未定義時に適用する値を指定できません。(例えば、Spring Frameworkが提供しているプレースホルダ機能では、「${プロパティ名:デフォルト値}
」という表現ができます)
そのため、Tomcat提供のプレースホルダ機能を使う場合は、「$CATALINA_BASE/conf/catalina.properties
」または「システムプロパティ(-Dプロパティ名=プロパティ値
)」に該当プロパティを定義しておかないと期待通りの動作になりません。
そんな時は・・・Tomcatのデフォルト実装をカスタマイズする?
Tomcat起動時のVM引数として「-Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.IntrospectionUtils.PropertySourceインタフェースの実装クラス
」を指定すると、指定したクラスがTomcatのデフォルト実装より優先的に使われます。
ためしに・・・Spring Frameworkが提供しているプレースホルダ機能でサポートされている「${プロパティ名:デフォルト値}
」という表現を可能にするクラスを作成してTomcatに適用してみます。(実装はかなり乱暴なので真似しないでくださいw)
<!-- 開発用のプロジェクトにorg.apache.tomcat.util.IntrospectionUtils.PropertySourceが格納されているアーティファクトを追加 -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>8.5.20</version>
<scope>provided</scope>
</dependency>
package com.example.tomcat.propertysource;
import org.apache.tomcat.util.IntrospectionUtils;
public class CustomTomcatPropertySource implements IntrospectionUtils.PropertySource {
@Override
public String getProperty(String key) {
String[] keyElements = key.split(":");
if (keyElements.length == 2) {
return System.getProperty(keyElements[0].trim(), keyElements[1].trim());
}
return null; // nullを返却するとTomcatのデフォ実装が利用される
}
}
org.apache.tomcat.util.IntrospectionUtils.PropertySource
インタフェースの実装クラスを格納したjarファイルを「$CATALINA_BASE/lib
」ディレクトリに格納し、Tomcat起動時のVM引数に「-Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=com.example.tomcat.propertysource.CustomTomcatPropertySource
」を指定します。
<session-config>
<session-timeout>${session.timeout:1}</session-timeout>
<!-- ... -->
</session-config>
こうすることで、Tomcat上でプレースホルダに対するデフォルト値を指定することができるようになります。
ってかweb.xml
としてはスキーマ違反ですw
ここまで紹介しておいてナンですが・・・ <session-timeout>
はweb.xml
のXSD上ではInteger型なので、IDE上ではスキーマ違反のエラーが出てしまうので、かなり微妙ですね。
まとめ
(やっぱりw)基本的にはweb.xml
上でプレースホルダ(環境依存値)を扱わないようにするのがよさそうです。
(仮に)使うとしても・・・スキーマ違反になるような使い方はよろしくないので、init-param
系のパラメータ値での利用にとどめておいた方よい気がします。