Post

Maven で servletContext の値を一元管理する方法

Maven で servletContext の値を一元管理する方法

概要

web.xmldisplay-name と、JSP で表示するバージョン番号を毎回手で両方直すのは面倒です。
実務では、pom.xml を単一の設定元にして、build 時に:

  • application.yml
  • web.xml

へ同じ値を流し込む形にすると管理しやすくなります。


やりたいこと

たとえば次の 2 箇所へ同じ版號を入れたいとします。

  • web.xmldisplay-name
  • JSP の ${initParam['sys_ver']} 用の servletContext 初期値

1. pom.xml に単一の値を置く

1
2
3
<properties>
    <app.sys-ver>202603311357</app.sys-ver>
</properties>

以後、版號はここだけ変更します。


2. application.yml は token にする

1
2
app:
  sys-ver: @app.sys-ver@

3. web.xml も同じ token を使う

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
         version="6.0"
         metadata-complete="false">
    <display-name>TsNoticeApproval_@app.sys-ver@</display-name>
</web-app>

4. application.yml だけ filtering する

src/main/resources 全体を filtering すると危険です。
application.yml だけに限定します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>false</filtering>
            <excludes>
                <exclude>application.yml</exclude>
            </excludes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
                <include>application.yml</include>
            </includes>
        </resource>
    </resources>

    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.4.0</version>
            <configuration>
                <delimiters>
                    <delimiter>@</delimiter>
                </delimiters>
                <useDefaultDelimiters>false</useDefaultDelimiters>
            </configuration>
        </plugin>
    </plugins>
</build>

5. web.xmlmaven-war-plugin で filtering する

web.xmlsrc/main/resources ではなく、src/main/webapp/WEB-INF にあるので、
maven-war-plugin 側で処理します。

1
2
3
4
5
6
7
8
9
10
11
12
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>3.4.0</version>
    <configuration>
        <delimiters>
            <delimiter>@</delimiter>
        </delimiters>
        <useDefaultDelimiters>false</useDefaultDelimiters>
        <filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
    </configuration>
</plugin>

6. servletContext に流し込む Java コード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package tw.edu.ntnu.itc.tsnoticeapproval.config;

import jakarta.servlet.ServletContext;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

/**
 * servletContext に sys_ver を設定する初期化クラス。
 */
@Component
public class SysVerContextInitializer implements ServletContextInitializer {
	private final Environment env;

	public SysVerContextInitializer(Environment env) {
		this.env = env;
	}

	@Override
	public void onStartup(ServletContext servletContext) {
		String sysVer = env.getProperty("app.sys-ver", "");
		servletContext.setInitParameter("sys_ver", sysVer);
	}
}

7. JSP 側の書き方

1
<div class="login-version">ver: ${initParam['sys_ver']}</div>

8. この方法の利点

  • 版號の変更箇所が pom.xml 1 か所だけになる
  • web.xmldisplay-name を維持できる
  • JSP 側の版號表示も同じ値になる
  • application.yml だけを限定して filtering するので事故が少ない
  • ${...} ではなく @...@ を使うため、Spring / JSP の式と衝突しにくい

完成形の最小例

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<properties>
    <app.sys-ver>202603311357</app.sys-ver>
</properties>

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>false</filtering>
            <excludes>
                <exclude>application.yml</exclude>
            </excludes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
                <include>application.yml</include>
            </includes>
        </resource>
    </resources>

    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.4.0</version>
            <configuration>
                <delimiters>
                    <delimiter>@</delimiter>
                </delimiters>
                <useDefaultDelimiters>false</useDefaultDelimiters>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>3.4.0</version>
            <configuration>
                <delimiters>
                    <delimiter>@</delimiter>
                </delimiters>
                <useDefaultDelimiters>false</useDefaultDelimiters>
                <filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
            </configuration>
        </plugin>
    </plugins>
</build>

application.yml

1
2
app:
  sys-ver: @app.sys-ver@

web.xml

1
<display-name>TsNoticeApproval_@app.sys-ver@</display-name>

SysVerContextInitializer

1
2
3
4
5
6
7
8
9
10
11
12
13
@Component
public class SysVerContextInitializer implements ServletContextInitializer {
	private final Environment env;

	public SysVerContextInitializer(Environment env) {
		this.env = env;
	}

	@Override
	public void onStartup(ServletContext servletContext) {
		servletContext.setInitParameter("sys_ver", env.getProperty("app.sys-ver", ""));
	}
}
This post is licensed under CC BY 4.0 by the author.