Spring Boot Profile使用

Spring Boot使用@Profile註解可以實現不同環境下配置參數的切換,任何@Component@Configuration註解的類都可以使用@Profile註解。

例如:

@Configuration
@Profile("production")
public class ProductionConfiguration {
    // ...
}

 通常,一個項目中可能會有多個profile場景,例如下面爲test場景:

@Configuration
@Profile("test")
public class TestConfiguration {
    // ...
}

 在存在多個profile情況下,你可以使用spring.profiles.active來設置哪些profile被激活。spring.profiles.include屬性用來設置無條件的激活哪些profile。

例如,你可以在application.properties中設置:

或者在application.yaml中設置:

spring.profiles.active屬性可以通過命令行參數或者資源文件來設置,其查找順序,請參考Spring Boot特性

自定義Profile註解

@Profile註解需要接受一個字符串,作爲場景名。這樣每個地方都需要記住這個字符串。Spring的@Profile註解支持定義在其他註解之上,以創建自定義場景註解。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Profile("dev")
public @interface Dev {
}

 這樣就創建了一個@Dev註解,該註解可以標識bean使用於@Dev這個場景。後續就不再需要使用@Profile("dev")的方式。這樣即可以簡化代碼,同時可以利用IDE的自動補全:)

多個Profile例子

下面是一個例子:

package com.javachen.example.service;
 
public interface MessageService {
  String getMessage();
}

 對於MessageService接口,我們可以有生產和測試兩種實現:

package com.javachen.example.service;
 
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
 
@Component
@Profile({ "dev" })
public class HelloWorldService implements MessageService{
 
  @Value("${name:World}")
  private String name;
 
  public String getMessage() {
    return "Hello " + this.name;
  }
 
}

 

package com.javachen.example.service;
 
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
 
@Component
@Profile({ "prod" })
public class GenericService implements MessageService {
 
  @Value("${hello:Hello}")
  private String hello;
 
  @Value("${name:World}")
  private String name;
 
  @Override
  public String getMessage() {
    return this.hello + " " + this.name;
  }
 
}

 Application類爲:

@SpringBootApplication
public class Application implements CommandLineRunner {
  private static final Logger logger = LoggerFactory.getLogger(Application.class);
 
  @Autowired
  private MessageService messageService;
 
  @Override
  public void run(String... args) {
    logger.info(this.messageService.getMessage());
    if (args.length > 0 && args[0].equals("exitcode")) {
      throw new ExitException();
    }
  }
 
  public static void main(String[] args) throws Exception {
    SpringApplication.run(Application.class, args);
  }
}

 實際使用中,使用哪個profile由spring.profiles.active控制,你在resources/application.properties中定義spring.profiles.active=XXX,或者通過-Dspring.profiles.active=XXXXXX可以是dev或者prod或者dev,prod需要注意的是:本例中是將@Profile用在Service類上,一個Service接口不能同時存在超過兩個實現類,故本例中不能同時使用dev和prod。

通過不同的profile,可以有對應的資源文件application-{profile}.properties。例如,application-dev.properties內容如下:

name=JavaChen-dev

 application-prod.properties內容如下:

接下來進行測試。spring.profiles.active=dev時,運行Application類,查看日誌輸出。

2016-02-22 15:45:18,470 [main] INFO  com.javachen.example.Application - Hello JavaChen-dev

spring.profiles.active=prod時,運行Application類,查看日誌輸出。

2016-02-22 15:47:21,270 [main] INFO  com.javachen.example.Application - Hello JavaChen-prod

logback配置多Profile

在resources目錄下添加logback-spring.xml,並分別對dev和prod進行配置:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--<include resource="org/springframework/boot/logging/logback/base.xml" />-->
 
    <springProfile name="dev">
        <logger name="com.javachen.example" level="TRACE" />
        <appender name="LOGFILE" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
            </encoder>
        </appender>
    </springProfile>
 
    <springProfile name="prod">
        <appender name="LOGFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <File>log/server.log</File>
            <rollingPolicy
                    class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <FileNamePattern>log/server_%d{yyyy-MM-dd}.log.zip</FileNamePattern>
            </rollingPolicy>
            <layout class="ch.qos.logback.classic.PatternLayout">
                <pattern>%date [%thread] %-5level %logger{80} - %msg%n</pattern>
            </layout>
        </appender>
    </springProfile>
 
    <root level="info">
        <appender-ref ref="LOGFILE" />
    </root>
 
    <logger name="com.javachen.example" level="DEBUG" />
</configuration>

 這樣,就可以做到不同profile場景下的日誌輸出不一樣。

maven中的場景配置

使用maven的resource filter可以實現多場景切換。

<profiles>
    <profile>
        <id>prod</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <build.profile.id>prod</build.profile.id>
        </properties>
    </profile>
    <profile>
        <id>dev</id>
        <properties>
            <build.profile.id>dev</build.profile.id>
        </properties>
    </profile>
</profiles>
 
<build>
        <filters>
            <filter>application-${build.profile.id}.properties</filter>
        </filters>
 
        <resources>
            <resource>
                <filtering>true</filtering>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
</build> 

 這樣在maven編譯時,可以通過-P參數指定maven profile即可。

總結

使用Spring Boot的Profile註解可以實現多場景下的配置切換,方便開發中進行測試和部署生產環境。

本文中相關代碼在github上面。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章