
SpringBootアプリケーションを開発する際に、開発時とプロダクション時でアプリケーションのプロパティを変更することはよくあります。今回はSpringBootアプリケーションのProfileを切り替えることでプロパティを環境に応じて変更する方法を紹介します。
見出し
はじめに
SpringBootのアプリケーションに限らず、環境に応じてプロパティの設定内容を切り替えることはよくあります。そういった環境のことをSpringBootではProfileと表現しています。Profileを切り替えることで、開発時には開発用のプロパティを利用し、プロダクション時にはプロダクション用のプロパティを利用することができます。
それでは、進めていきましょう。
前提
前提として、以下がインストールされている必要があります。
- Javaがインストール済みであること
- Spring CLIがインストール済みであること
細かいバージョンは’環境を参照して下さい。
サンプルプロジェクトを作る
プロジェクトの作成
$ spring init --build=maven --java-version=10 --boot-version=2.0.3.RELEASE -d=web springboot-profile
$ cd springboot-profile/
$ ls
mvnw* mvnw.cmd pom.xml src/
$ touch src/main/java/com/example/springbootprofile/DemoConfig.java
$ touch src/main/java/com/example/springbootprofile/DemoController.java
$ tree src/main/
src/main/
├── java
│ └── com
│ └── example
│ └── springbootprofile
│ ├── DemoApplication.java
│ ├── DemoConfig.java
│ └── DemoController.java
└── resources
├── application.properties
├── static
└── templates
pom.xml
今回の主題ではありませんが、「@ConfigurationProperties」を使いたいので、POMに「spring-boot-configuration-processor」の設定を追加します。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>springboot-profile</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>10</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
message=Hello, Any Profile!
demo-config.app-name=Spring Boot Profile
demo-config.app-description="${demo-config.app-name}" is a demo application.
DemoApplication.java
package com.example.springbootprofile;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
@EnableConfigurationProperties
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
DemoConfig config = (DemoConfig) ctx.getBean("demoConfig");
System.out.println(config.toString());
}
}
DemoConfig.java
package com.example.springbootprofile;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "demo-config")
public class DemoConfig {
private String appName;
private String appDescription;
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public String getAppDescription() {
return appDescription;
}
public void setAppDescription(String appDescription) {
this.appDescription = appDescription;
}
@Override
public String toString() {
return "DemoConfig{" +
"appName='" + appName + '\'' +
", appDescription='" + appDescription + '\'' +
'}';
}
}
DemoController.java
package com.example.springbootprofile;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@Value("${message}")
private String message;
@RequestMapping("/")
public String demo() {
return message;
}
}
動作確認
アプリケーションが動くことを確認しましょう。
$ ./mvnw spring-boot:run
...
DemoConfig{appName='Spring Boot Profile', appDescription='"Spring Boot Profile" is a demo application.'}
...
Demo-configのプロパティが正しく設定されています。
$ curl localhost:8080/
Hello, Any Profile!
Messageのプロパティが正しく設定されています。
プロパティファイルによるProfileの切り替え
それでは、まずはプロパティファイルをProfile毎に切り替えられるようにしましょう。
開発用とプロダクション用のプロパティファイルを作る
$ touch src/main/resources/application-dev.properties
$ touch src/main/resources/application-prod.properties
application-dev.properties
message=Hello, Development Profile!
demo-config.app-name=Spring Boot Development Profile
demo-config.app-description="${demo-config.app-name}" is a development application.
application-prod.properties
message=Hello, Production Profile!
demo-config.app-name=Spring Boot Production Profile
demo-config.app-description="${demo-config.app-name}" is a production application.
Profileを切り替えて動作確認
Profileがdevの場合
$ ./mvnw spring-boot:run -Dspring.profiles.active="dev"
...
DemoConfig{appName='Spring Boot Development Profile', appDescription='"Spring Boot Development Profile" is a development application.'}
$ curl localhost:8080/
Hello, Development Profile!
Profileがprodの場合
$ ./mvnw spring-boot:run -Dspring.profiles.active="prod"
...
DemoConfig{appName='Spring Boot Production Profile', appDescription='"Spring Boot Production Profile" is a production application.'}
$ curl localhost:8080/
Hello, Production Profile!
正しく切り替わっていることが確認できました。
YAMLファイルによるProfileの切り替え
次はYAMLファイルを切り替えられるようにしましょう。また、プロパティファイルとYAMLファイルがある場合、プロパティファイルが優先されるので、先程作った不要なプロパティファイルは削除しておきましょう。
開発用とプロダクション用のYAMLファイルを作る
$ touch src/main/resources/application-dev.yml
$ touch src/main/resources/application-prod.yml
application-dev.yml
message: Hello, Development Profile!
demo-config:
app-name: Spring Boot Development Profile
app-description: \"${demo-config.app-name}\" is a development application.
application-prod.yml
message: Hello, Production Profile!
demo-config:
app-name: Spring Boot Production Profile
app-description: \"${demo-config.app-name}\" is a production application.
Profileを切り替えて動作確認
Profileがdevの場合
$ ./mvnw spring-boot:run -Dspring.profiles.active="dev"
...
DemoConfig{appName='Spring Boot Development Profile', appDescription='\"Spring Boot Development Profile\" is a development application.'}
$ curl localhost:8080/
Hello, Development Profile!
Profileがprodの場合
$ ./mvnw spring-boot:run -Dspring.profiles.active="prod"
...
DemoConfig{appName='Spring Boot Production Profile', appDescription='\"Spring Boot Production Profile\" is a production application.'}
$ curl localhost:8080/
Hello, Production Profile!
正しく切り替わっていることが確認できました。
まとめて書く
YAMLファイルの場合は、「application.yaml」ファイルに以下のようにまとめて書くこともできます。
---
spring:
profiles: dev
message: Hello, Development Profile!
demo-config:
app-name: Spring Boot Development Profile
app-description: \"${demo-config.app-name}\" is a development application.
---
spring:
profiles: prod
message: Hello, Production Profile!
demo-config:
app-name: Spring Boot Production Profile
app-description: \"${demo-config.app-name}\" is a production application.
YAMLは使いやすいですね。
アノテーションによるProfileの切り替え
最後にアノテーションでプロファイルを切り替えていきましょう。
設定用のクラスを作る
$ touch src/main/java/com/example/springbootprofile/DataSource.java
$ touch src/main/java/com/example/springbootprofile/DataSourceConfig.java
DataSource.java
package com.example.springbootprofile;
public class DataSource {
private String message;
private String appName;
private String appDescription;
public DataSource() {
}
public DataSource(String message, String appName, String appDescription) {
this.message = message;
this.appName = appName;
this.appDescription = appDescription;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public String getAppDescription() {
return appDescription;
}
public void setAppDescription(String appDescription) {
this.appDescription = appDescription;
}
@Override
public String toString() {
return "DataSource{" +
"message='" + message + '\'' +
", appName='" + appName + '\'' +
", appDescription='" + appDescription + '\'' +
'}';
}
}
DataSourceConfig.java
package com.example.springbootprofile;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
public class DataSourceConfig {
@Bean(name = "datasource")
@Profile("dev")
DataSource development() {
return new DataSource("Hello, Development Profile!", "Spring Boot Development Profile","\"Spring Boot Development Profile\" is a development application.");
}
@Bean(name = "datasource")
@Profile("prod")
DataSource production() {
return new DataSource("Hello, Production Profile!", "Spring Boot Production Profile","\"Spring Boot Production Profile\" is a production application.");
}
}
DemoApplication.java
DataSouceのクラスを使うように修正します。
package com.example.springbootprofile;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
DataSource config = (DataSource) ctx.getBean("datasource");
System.out.println(config.toString());
}
}
DemoController.java
DataSouceのクラスを使うように修正します。
package com.example.springbootprofile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@Autowired
@Qualifier("datasource")
private DataSource dataSource;
@RequestMapping("/")
public String demo() {
return dataSource.getMessage();
}
}
Profileを切り替えて動作確認
Profileがdevの場合
$ ./mvnw spring-boot:run -Dspring.profiles.active="dev"
...
DataSource{message='Hello, Development Profile!', appName='Spring Boot Development Profile', appDescription='"Spring Boot Development Profile" is a development application.'}
$ curl localhost:8080/
Hello, Development Profile!
Profileがprodの場合
$ ./mvnw spring-boot:run -Dspring.profiles.active="prod"
...
DataSource{message='Hello, Production Profile!', appName='Spring Boot Production Profile', appDescription='"Spring Boot Production Profile" is a production application.'}
$ curl localhost:8080/
Hello, Production Profile!
正しく切り替わっていることが確認できました。
おまけ(いろいろなProfileの指定方法)
今回はProfileの指定をMavenの引数から行いましたが、他にも方法があります。おまけとして紹介します。
IntelliJのIDE上での引数による指定
Program argumentsに「–spring.profiles.active=dev」を指定することで、開発中にIDEから切り替えられます。
Mavenの引数による指定
$ ./mvnw spring-boot:run -Dspring.profiles.active="dev"
プロパティファイルによる指定
application.propertiesに以下を記載する。
spring.profiles.active=dev
YAMLファイルによる指定
application.ymlに以下を記載する。
spring:
profiles:
active: dev
最後に
いかがでしたか?これでSpringBootアプリケーションで環境毎にプロパティを使い分けることができるようになったと思います。では。
環境
- PC : macOS High Sierra 10.13.5
- Java : openjdk version “10.0.1” 2018-04-17
- Spring CLI : v2.0.2.RELEASE

