Spring Boot @ConfigurationProperties:将外部配置绑定到 POJO 类上

x33g5p2x  于2021-10-17 转载在 Spring  
字(7.8k)|赞(0)|评价(0)|浏览(305)

在本文中,您将学习如何通过名为 @ConfigurationProperties 的非常简单的基于注解的 API 在 Spring Boot 中定义和使用外部配置。

@ConfigurationProperties 将外部配置绑定到应用程序代码中的强类型 bean。您可以像任何其他 spring bean 一样在整个应用程序代码中注入和使用这个 bean。

让探索开始吧!

创建应用程序

让我们创建一个示例应用程序来学习如何在 Spring Boot 中定义和使用外部配置。

我们将使用 Spring Boot CLI 来初始化项目。启动终端并输入以下命令以生成项目 -

spring init --dependencies=web,validation --name=config-properties-demo --package-name=com.example.demo config-properties-demo

或者,您也可以按照以下说明从 Spring Initializr 网站引导应用程序 -

  1. 前往http://start.spring.io
  2. Artifact 字段中输入 config-properties-demo
    1.设置包名为com.example.demo
  3. dependencies 部分添加 WebValidation
  4. 点击Generate Project下载项目。

以下是完整应用的目录结构,供大家参考——

定义属性

Spring Boot 应用程序默认从位于类路径中的 application.properties 文件加载配置属性。

打开 src/main/resources/application.properties 文件并向其添加以下属性 -

## Top level app properties
app.name=ConfigurationPropertiesDemoApp
app.description=${app.name} is a spring boot app that demonstrates how to use external configuration properties
app.upload-dir=/uploads

app.connect-timeout=500ms
app.read-timeout=10s

## Nested Object Properties (security)
app.security.username=callicoder
app.security.password=123456
app.security.roles=USER,ADMIN,PARTNER # List Property
app.security.enabled=true

## Map Properties (permissions)
app.security.permissions.CAN_VIEW_POSTS=true
app.security.permissions.CAN_EDIT_POSTS=true
app.security.permissions.CAN_DELETE_POSTS=false
app.security.permissions.CAN_VIEW_USERS=true
app.security.permissions.CAN_EDIT_USERS=true
app.security.permissions.CAN_DELETE_USERS=false

使用@ConfigurationProperties 将外部属性绑定到 POJO 类

现在让我们看看如何使用 @ConfigurationPropertiesapplication.properties 文件中定义的属性绑定到 POJO 类。

@ConfigurationProperties 注释采用 prefix 参数,并将具有指定前缀的所有属性绑定到 POJO 类 -

package com.example.demo.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DurationUnit;

import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@ConfigurationProperties(prefix = "app")
public class AppProperties {
    private String name;
    private String description;
    private String uploadDir;
    private Duration connectTimeout = Duration.ofMillis(1000);
    @DurationUnit(ChronoUnit.SECONDS)
    private Duration readTimeout = Duration.ofSeconds(30);
    private final Security security = new Security();

    // Getters and Setters (Omitted for brevity)

    public static class Security {
        private String username;
        private String password;
        private List<String> roles = new ArrayList<>();
        private boolean enabled;
        private Map<String, String> permissions = new HashMap<>();

        // Getters and Setters (Omitted for brevity)
    }
}

让我们了解有关绑定的一些细节:

类型安全绑定(列表和映射)

注意属性文件中逗号分隔的 roles 是如何绑定到角色的 List 的,而 permissions 是绑定到 Map 的。
*
持续时间支持

另外,请注意持续时间属性如何安全地绑定到 Duration 类型。这太棒了。 Spring Boot 允许您在 application.properties 文件中使用以下单位指定持续时间 -

  • ns 纳秒
  • us 为微秒
  • ms 毫秒
  • s
  • m 分钟
  • h 数小时
  • d 几天

默认单位是 milliseconds。所以如果你没有在属性文件中指定任何单位,它会被认为是 milliseconds

请注意,您也可以使用 @DurationUnit 注释覆盖单元,就像我们在上面的 POJO 类中所做的那样。

命名约定

所有 kebab case 属性名称(例如:upload-dir)都绑定到 POJO 类中相应的驼峰式大小写字段(例如:uploadDir)。

请注意,也可以在驼峰式大小写中指定属性。但建议使用烤肉串。

启用配置属性

您需要使用 @EnableConfigurationProperties 注释显式注册属性类,如下例所示。

package com.example.demo;

import com.example.demo.config.AppProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties(AppProperties.class)
public class ConfigPropertiesDemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigPropertiesDemoApplication.class, args);
	}
}

或者,您还可以向 AppProperties 类添加 @Component 注释,并且绑定仍然有效。

在 Spring Bean 中注入配置属性

@ConfigurationProperties 类是普通的 spring bean,您可以像注入任何其他 bean 一样注入它们。

在下面的示例中,我编写了一个示例 API,它从配置属性中检索应用程序详细信息并将它们返回给客户端 -

package com.example.demo.controller;

import com.example.demo.config.AppProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class IndexController {

    // Injecting ConfigurationProperties in your Beans
    @Autowired
    private AppProperties appProperties;

    @GetMapping("/")
    public Map<String, String> getAppDetails() {
        Map<String, String> appDetails = new HashMap<>();
        appDetails.put("name", appProperties.getName());
        appDetails.put("description", appProperties.getDescription());

        return appDetails;
    }
}

@ConfigurationProperties 验证

您可以使用 javax.validation 约束(如 @NotNull@NotEmpty 等)来验证配置属性。

要启用验证,您只需要在 @ConfigurationProperties 类中添加 Spring 的 @Validated 批注 -

package com.example.demo.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DurationUnit;
import org.springframework.validation.annotation.Validated;

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@ConfigurationProperties(prefix = "app")
@Validated
public class AppProperties {
    @NotNull
    private String name;
    private String description;
    private String uploadDir;
    private Duration connectTimeout = Duration.ofMillis(1000);
    @DurationUnit(ChronoUnit.SECONDS)
    private Duration readTimeout = Duration.ofSeconds(30);
    @Valid
    private final Security security = new Security();

    // Getters and Setters (Omitted for brevity)

    public static class Security {
        private String username;
        private String password;
        @NotEmpty
        private List<String> roles = new ArrayList<>();
        private boolean enabled;
        private Map<String, String> permissions = new HashMap<>();

        // Getters and Setters (Omitted for brevity)
    }
}

现在,如果 name 属性为 nullsecurity.roles 属性为空,Spring Boot 应用程序将在启动时抛出验证异常。

基于环境(特定于配置文件)的配置属性

除了标准的 application.properties 文件之外,Spring Boot 还允许您使用以下命名约定定义特定于配置文件的属性 -

application-{profile}.properties

配置文件特定的属性文件从与 application.properties 文件相同的位置加载,配置文件特定的属性始终覆盖默认属性。

为了说明这一点,让我们定义一些特定于配置文件的属性文件,并覆盖一些默认属性 -

应用程序-dev.properties

## Override properties for dev environment
app.name=ConfigurationPropertiesDemoApp-DEVELOPMENT

app.security.username=callicoder-dev

application-staging.properties

## Override properties for staging environment
app.name=ConfigurationPropertiesDemoApp-STAGING

app.security.username=callicoder-staging
app.security.password=C@ll1C0d3r

应用程序-prod.properties

## Override properties for prod environment
app.name=ConfigurationPropertiesDemoApp-PRODUCTION

app.security.username=callicoder-prod
app.security.password=C@ll1C0d3r

现在,我们需要激活一个 spring 配置文件,以便 spring boot 加载相应的属性文件。

激活 Spring 配置文件

您可以通过多种方式设置活动配置文件 -

使用应用程序属性

默认的 application.properties 文件总是由 Spring Boot 加载。您可以通过添加以下属性在 application.properties 文件中设置活动配置文件 -

spring.profiles.active=staging

后添加上述属性,Spring Boot 也会加载 application-staging.properties 文件,并使用在那里指定的新值覆盖属性。
1.
使用命令行参数

您可以通过提供 spring.profiles.active 命令行参数来设置启动时的活动配置文件 -

# Packaging the app
mvn clean package -Dspring.profiles.active=staging

# Running the packaged jar with `spring.profiles.active` argument
java -jar -Dspring.profiles.active=staging target/config-properties-demo-0.0.1-SNAPSHOT.jar

此外,这是在使用 spring-boot:run 命令运行应用程序时设置活动配置文件的方法 -

mvn spring-boot:run -Dspring.profiles.active=dev

使用环境变量

最后,您还可以使用 SPRING_PROFILES_ACTIVE 环境变量设置活动配置文件-

export SPRING_PROFILES_ACTIVE=prod

运行应用程序

让我们运行应用程序并访问示例 Rest API 以查看操作中的配置属性 -

mvn spring-boot:run
$ curl http://localhost:8080
{"name":"ConfigurationPropertiesDemoApp","description":"ConfigurationPropertiesDemoApp is a spring boot app that demonstrates how to use external configuration properties"}

使用设置为 prod 的活动配置文件运行应用程序

mvn spring-boot:run -Dspring.profiles.active=prod
$ curl http://localhost:8080
{"name":"ConfigurationPropertiesDemoApp-PRODUCTION","description":"ConfigurationPropertiesDemoApp-PRODUCTION is a spring boot app that demonstrates how to use external configuration properties"}

结论

@ConfigurationProperties 是一种以类型安全的方式绑定外部配置的非常好的方法。我几乎在所有项目中都使用此功能。此外,Spring Boot 的自动配置也依赖于配置属性。

相关文章