LoginSignup
0
1

More than 3 years have passed since last update.

SpringBoot で起動引数による環境切替を行う

Last updated at Posted at 2020-01-21

はじめに

SpringBoot でバックエンドを開発しているときにある話。

昨今、Dockerが出てきてから結合から本番までワンモジュール、ワンソースで最後まで管理する傾向にある。

各環境の区別は、環境引数を外から渡すだけ、という設計方針にした際に、
では、中身のSpringBootで作ったアプリケーションのモジュールはどういう風にすればよいのかをまとめる

環境の数が少ないなら

SpringBootのProfileで切替すればよい。

下記に公式情報があるため、こちらで実現できます。
公式

起動引数に下記を含めれば、
-Dspring.profiles.active=dev1

下記ファイルが読み込まれる仕様である。
src/main/resource/application-dev1.properties」

ビルドでプロパティファイルを切替

mavenのprofile切替が簡単。

モジュールを固める、jar やwar などにするときに、maven の機能で設定ファイルの切り替えを行う。
ビルド時にファイル移送を実施するため、設定ファイルの切替で最も簡単な方法。

mvn package -P dev01

pom.xml



<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
        <webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory>
        <webResources>
            <resource>
                <directory>${basedir}/release/${project.stage}</directory>
            </resource>
        </webResources>
        <useCache>false</useCache>
<!-- 警告エラーが発生するため追加-->                  <failOnMissingWebXml>false</failOnMissingWebXml>
        <archive>
            <manifest>
<!-- main クラス指定(必要に応じて)-->                            <mainClass>jp.co.●●.●●.Main</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

<profiles>
    <profile>
        <id>dev1</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <project.stage>dev01</project.stage>
        </properties>
    </profile>

    <profile>
        <id>dev02</id>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
        <properties>
            <project.stage>dev02</project.stage>
        </properties>
    </profile>
</profiles>

シェルコマンドを内部に組み込むことも可能なため、
maven に慣れている人にとっては、なじみ深い。

ワンモジュールで環境切替したい

今までの問題点

1つ目、springboot のprofile 切替方法は、プロパティファイルの形式が固定されており、複数のファイルの読み込みなどの設定が非常にやりづらい。特に環境が増えた場合に柔軟性に欠ける。

2つ目、maven のprofile 切替方法は、複数ファイルの読み込みは、特定の環境には特定のモジュールしか動かない設定のため、デプロイシェル等に誤りや手順ミスがあった場合に、障害が発生する可能性が高い。

spring bootのprofile 機能拡張を利用する。

ApplicationContextInitializerを利用して起動時にprofileを設定するようにする。

Javaの起動引数指定 → ApplicationContextInitializerでprofileに指定
この方法の場合、profile 指定するときに、グルーピングできるようになり、
dev01で実行すると、dev とdev01の二つの情報を含めることができる。

java -Dproject.stage=dev01 hoge.war

public class SpringActiveProfileInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    /** ロガー */
    private static final Logger LOG = LoggerFactory.getLogger(SpringActiveProfileInitializer.class);

    @Override
    public void initialize(final ConfigurableApplicationContext applicationContext) {

        // 起動引数を取得(dev01)
        String projectStage = System.getProperty("project.stage");

        // 起動グループを取得(dev)
        String prjectStageGroup = projectStage.replaceAll("[0-9]+", "");
        ConfigurableEnvironment env = applicationContext.getEnvironment();
        if (StringUtils.equals(projectStage, prjectStageGroup)) {
            env.setActiveProfiles(projectStage);
        } else {
            env.setActiveProfiles(prjectStageGroup);
            env.addActiveProfile(projectStage);
        }

        if (LOG.isDebugEnabled()) {
            //  setting spring.profiles.active = [dev, dev01]
            LOG.debug("setting spring.profiles.active = {}", Arrays.asList(env.getActiveProfiles()));
        }
    }
}

web-fragment.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-fragment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:webfragment="http://xmlns.jcp.org/xml/ns/javaee/web-fragment_3_0.xsd" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-fragment_3_0.xsd"
    version="3.0">
    <!-- JVMシステムパラメータで設定したProjectStageをSpringActiveProfileへ設定 -->
    <context-param>
        <param-name>contextInitializerClasses</param-name>
        <param-value>jp.co.future.project.palette.common.context.SpringActiveProfileInitializer</param-value>
    </context-param>

</xml>

spring bootのprofile はxml でも利用可能

xml 内部でもprofile を記載でき、
環境ごとに定義ファイルの切り分けられる

サンプルで記載しているが、共通化や外部ファイルの読み込みなどの設定も可能。


    <beans profile="dev">
        <!-- データソース -->
        <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
            <property name="jdbcUrl" value=""/>
        </bean>
    </beans>

    <beans profile="stg">
        <!-- データソース -->
        <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
            <property name="jdbcUrl" value=""/>
        </bean>
    </beans>

    <!-- カンマ区切りで複数ステージの指定も可能 -->
    <beans profile="dev,stg">
        <bean id="redis" >
        </bean>
    </beans>


    <beans profile="dev01">
        <!-- xmlからプロパティファイルの読み込みも可能 -->
        <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
            <property name="location" value="classpath:config/connect-config-dev01.properties" />
        </bean>
    </beans>

    <!-- xmlそのものをインポートすることも可能 -->
    <import resource="classpath:META-INF/common-context.xml" />

おわりに

以上、spring boot で環境切替を行う方法でした。
ワンモジュール、ワンソース!

0
1
0

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
0
1