Spring Boot Profile使用

本文介绍如何使用SpringBoot的@Profile注解实现不同环境下的配置切换,包括开发和生产环境。通过具体示例展示了如何定义和服务不同场景的配置文件,并在日志配置和Maven构建过程中应用多环境配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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中设置:

spring.profiles.active=dev,hsqldb

或者在application.yaml中设置:

spring.profiles.active:dev,hsqldb

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内容如下:

name=JavaChen-prod

接下来进行测试。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上面。

### Spring Boot Profile Usage and Configuration In the context of Spring Boot, profiles serve as a mechanism to segregate configurations based on environments such as development, testing, or production. The application can load different settings depending on which profile is active. Configuration properties are managed through `application.properties` or `application.yml`, where specific files like `application-{profile}.properties` allow for environment-specific overrides[^1]. For instance, an `application-dev.properties` file would contain settings applicable only when the "dev" profile is activated. The activation of these profiles occurs via several methods: - **Command Line Argument:** By passing `-Dspring.profiles.active=profileName`. - **Environment Variable:** Setting `SPRING_PROFILES_ACTIVE=profileName`. - **Programmatic Approach:** Before invoking `SpringApplication.run()`, one may call `SpringApplication.setAdditionalProfiles("profileName")`. Implementing the `ConfigurableEnvironment` interface also provides flexibility in setting up profiles programmatically[^3]. For applications utilizing Spring Cloud Vault, secrets management integrates seamlessly with profiles by searching paths that include both the application name and its active profile(s). This ensures secure storage and retrieval of sensitive information without hardcoding it into source-controlled repositories[^4]. When developing multi-environment applications using Spring Boot, leveraging profiles simplifies managing varying configurations across distinct deployment scenarios while maintaining codebase consistency. ```java // Example demonstrating programmatic profile setup before running SpringApplication. import org.springframework.boot.SpringApplication; public class Application { public static void main(String[] args) { SpringApplication app = new SpringApplication(Application.class); app.setAdditionalProfiles("prod"); // Set 'prod' as additional profile app.run(args); } } ``` --related questions-- 1. How does Spring Boot handle multiple active profiles simultaneously? 2. What mechanisms exist within Spring Boot for overriding default property values per environment? 3. Can you provide examples of how security credentials might be stored securely using Spring Cloud Vault alongside profiles? 4. In what ways do externalized configuration sources interact with each other in terms of precedence order during startup?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值