LoginSignup
11
11

More than 5 years have passed since last update.

Tomcatだとweb.xml内でプレースホルダ(${...})が使えるのです

Last updated at Posted at 2017-09-12

長年Tomcatを使っていますが、(ふとしたことから)web.xmlの中でプレースホルダ(${...})が使えることを初めて知りました。
(Tomcat固有の設定ファイル(server.xmlcontext.xml)で使えるのは知っていましたが・・・)

Important:

念のため・・プレースホルダは、Servlet APIの仕様ではありませんので、勘違いしないように!!

とりあえずプレースホルダを使ってみる

ここでは、セッションタイムアウト時間をプレースホルダ化しておき、システムプロパティから実際の値を取得してみます。

web.xml
<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

pom.xml
<!-- 開発用のプロジェクトに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>
IntrospectionUtils.PropertySourceの実装クラス
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」を指定します。

web.xml
<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系のパラメータ値での利用にとどめておいた方よい気がします。

参考サイト

11
11
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
11