目录
Spring Boot 的外部化配置允许您在不同环境之间轻松切换配置而无需改动代码。常见的做法是使用 `application.properties` 或 `application.yml` 文件,同时也支持环境变量、命令行参数等多种配置方式。以下是让我们以 `application.yml` 文件作为一个外部化配置例子进行举例,并通过不同方式进行配置覆盖。
1. `application.yml` 中配置属性
首先,在 `src/main/resources/application.yml` 中定义配置属性。
`application.yml`
myapp:
message: "Hello from application.yml"
2. 实现调用例子
2.1. 创建配置类
开始,我们需要创建一个配置类来绑定配置文件的属性。
`MyConfiguration.java`
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "myapp")
public class MyConfiguration {
private String message;
// standard getters and setters
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
2.2. 使用配置类
接下来,我们在服务中使用这个配置。
`HelloService.java`
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class HelloService {
private final MyConfiguration config;
@Autowired
public HelloService(MyConfiguration config) {
this.config = config;
}
public String greet() {
return config.getMessage();
}
}
2.3. 创建 REST 控制器
创建一个控制器来使用 `HelloService`。
`GreetingController.java`
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GreetingController {
private final HelloService helloService;
@Autowired
public GreetingController(HelloService helloService) {
this.helloService = helloService;
}
@GetMapping("/greet")
public String greet() {
return helloService.greet();
}
}
2.4. 编写测试
编写测试来验证配置是如何被加载的。
`GreetingControllerTest.java`
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class GreetingControllerTest {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
public void greetingShouldReturnDefaultMessage() throws Exception {
assertThat(this.restTemplate.getForObject("http://localhost:" + port + "/greet",
String.class)).contains("Hello from application.yml");
}
}
2.5. 验证测试
运行 `GreetingControllerTest` 以确保应用加载了 `application.yml` 中的配置,并返回了正确的消息。
3. 配置覆盖
3.1. 覆盖方式优先级阐述
Spring Boot 的外部化配置系统是灵活的,并且支持多种配置方式。当通过不同的方法设置同一个属性时,Spring Boot 会根据以下优先级来决定使用哪个值:
No1. 命令行参数:比如使用 `java -jar app.jar --property.name=value` 来传递参数。
No2. 来自SPRING_APPLICATION_JSON的属性:通过环境变量或系统属性提供的嵌入在 `SPRING_APPLICATION_JSON` 中的 JSON 数据。
No3. Java系统属性(System.getProperties()):通常通过 `-Dproperty.name=value` 形式的 JVM 参数传递。
No4. **操作系统环境变量: 直接来自操作系统的环境变量。
No5. application.properties 或 application.yml 文件中的配置:
- 位于 JAR 包外部的 `/config` 子目录中。
- 位于 JAR 包外部的当前目录中。
- 位于 JAR 包内部的 `/config` 包中。
- 位于 JAR 包内部的根目录中。
No6. 在 @Configuration 注解类上使用 @PropertySource:当你使用 `@PropertySource` 注解来指定属性文件时。
No7. 通过 SpringApplication.setDefaultProperties 方法配置的默认属性: 这在你的主程序或应用启动类中通过编程的方式设置。
这些来源按照上述顺序排序,列表上面的配置源会覆盖下面的配置源。因此,命令行参数的优先级最高,会覆盖所有其他的配置源,而通过 `SpringApplication.setDefaultProperties` 设置的属性优先级最低。需要注意的是,当使用 Spring Cloud 等其他配置服务器时,可能会引入其他配置源,这可能会改变上述顺序。
3.2. 覆盖配置举例复现
在 Spring Boot 应用程序中,可以使用多种方法来提供外部配置,命令行参数、环境变量可以很容易地在应用程序启动时被注入,并且会覆盖 `application.properties` 或 `application.yml` 中定义的属性值。这种方式非常适用于在不同环境之间移植应用程序,例如从开发环境到测试环境,再到生产环境,因为它允许你在不更改代码的情况下调整配置。下面重点对其进行举例实现:
3.2.1. 命令行参数覆盖
可以通过命令行参数来覆盖 `application.yml` 中的配置。例如:
java -jar myapp.jar --myapp.message="Hello from command line"
3.2.2. 环境变量覆盖
可以设置一个环境变量来覆盖 `application.yml` 中的配置。例如:
在 UNIX/Linux 系统中
###打开你的终端或者在部署脚本中,设置环境变量 `MYAPP_MESSAGE`:
export MYAPP_MESSAGE="Hello from the environment variable"
###然后启动你的 Spring Boot 应用程序:
java -jar target/myapp-0.0.1-SNAPSHOT.jar
或者,你也可以在一行命令中设置环境变量并启动应用程序,这样设置的环境变量只会在这次执行中有效:
MYAPP_MESSAGE="Hello from the environment variable" java -jar target/myapp-0.0.1-SNAPSHOT.jar
在 Windows 系统中
###在命令提示符(cmd)中,你会使用 `set` 命令来设置环境变量:
set MYAPP_MESSAGE=Hello from the environment variable
###然后,和在 Linux 中一样,启动你的应用程序:
java -jar target/myapp-0.0.1-SNAPSHOT.jar
在 Docker 容器中
###如果你正在使用 Docker,你可以在 `docker run` 命令中使用 `-e` 选项来设置环境变量:
docker run -e MYAPP_MESSAGE="Hello from the environment variable" -p 8080:8080 myapp:latest
在上述所有情况中,Spring Boot 会优先读取环境变量 。
4. 总结
Spring Boot 的外部化配置功能非常强大,它支持类型安全的配置(通过 `@ConfigurationProperties`),允许您使用属性文件、YAML 文件、环境变量和命令行参数等来定义配置。
本文中,我们展示了如何使用 `application.yml` 来外部化配置,并通过测试来验证配置的加载。我们使用 `@SpringBootTest` 来启动一个真实的应用上下文,并使用随机端口启动服务器,然后使用 `TestRestTemplate` 来调用端点并检查返回的消息。同时,我们配置覆盖的方式、优先级做了介绍及重点复现。希望能更好的帮助各位朋友们!!