Spring Boot 配置属性解释

27,813次阅读
没有评论

共计 9486 个字符,预计需要花费 24 分钟才能阅读完成。

在 Spring Boot 中,配置注解可能会让您感到困惑。这些注解包括 @Configuration、@EnableConfigurationProperties、@ConfigurationPropertiesScan 等。这些注解实际上是什么,以及如何在代码中使用它们呢?

本文的目标是解释这些不同的选项,解释它们之间的差异,并通过示例展示如何使用它们。

简介

在 Spring Boot 中,配置属性是一种可以设置和配置应用程序的行为和设置的方式。这些属性可以被定义在不同的位置,如 application.properties、application.yml、配置类中,也可以通过命令行参数或环境变量进行设置。

Spring Boot 提供了一个强大的属性配置系统,使得开发者可以轻松地设置和管理应用程序的配置。

通过实际的应用我们会很好理解,加上可以在官方 Spring Boot 文档 (https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/) 中找到(搜索配置)。然而,在我看来,它缺乏明确的例子。这就是本文的目标:解释不同的选项,解释差异,并通过示例展示如何使用它们。

本文中使用的源代码可以在 GitHub 上找到。(https://github.com/mydeveloperplanet/MySpringBootConfigurationPlanet)

申请样本

示例应用程序是使用 start.spring.io(https://start.spring.io/)创建的,并利用 Spring Web 和 Lombok 依赖项。

本节概述如何设置存储库和基本应用程序。详细内容将在后面的章节中明确。

这些属性位于 MyProperties 类中,包括:

  • 一个布尔值 enabled;

  • 一个字符串 stringConfig;

  • 嵌套 additional 配置项由以下部分组成:

布尔值包含其默认值,字符串值将在文件中指定一个值 application.properties。属性的值 addString 还将包含对该 stringConfig 属性的引用。这样,您就可以组合属性值。

属性文件 1

my.properties.string-config=First piece
my.properties.additional.add-string=${my.properties.string-config} Second piece

添加了一个 ConfigurationController,它读取配置属性并返回它们。

@RequestMapping("/configuration")
public String configuration() {StringBuilder result = new StringBuilder();
    result.append("Value of enabled =").append(myProperties.isEnabled()).append("n");
    result.append("Value of stringConfig =").append(myProperties.getStringConfig()).append("n");
    if (myProperties.getAdditional() != null) {result.append("Value of additional.addEnabled =").append(myProperties.getAdditional().isAddEnabled()).append("n");
        result.append("Value of additional.addString =").append(myProperties.getAdditional().getAddString()).append("n");
    }
    return result.toString();}

该应用程序由多个模块组成。每个模块对应于本文中涵盖的不同主题。

构建应用程序:

$ mvn clean verify

导航到模块的目录并运行应用程序:

$ mvn spring-boot:run

端点可以按如下方式调用:

$ curl http://localhost:8080/configuration

每个模块包含三个测试:

  • HttpRequestIT:此测试将使用注释启动一个完整的服务器 @SpringBootTest;

  • WebLayerIT:此测试使用注释启动具有有限数量的 bean 的应用程序上下文 @WebMvcTest;

  • WebLayerTestPropertiesIT:与 相同 WebLayerIT,但这次使用特定的应用程序属性。

@ConfigurationProperties + @Component

在模块 config1 中,您将通过 @ConfigurationProperties 注释将属性映射到配置类 MyProperties。为了在控制器中使用它,您还需要添加 @Component 注释。另请注意,MyProperties 类中需要提供 setter 和 getter,它们是通过 @Getter 和 @Setter Lombok 注释生成的。

MyProperties 类如下:

@Getter
@Setter
@Component
@ConfigurationProperties("my.properties")
public class MyProperties {
 
    private boolean enabled;
 
    private String stringConfig;
 
    private final Additional additional = new Additional();
 
    @Getter
    @Setter
    public static class Additional {
 
        private boolean addEnabled;
 
        private String addString;
 
    }
 
}

在控制器中,您只需注入 MyProperties 组件即可。

@RestController
public class ConfigurationController {
 
    private final MyProperties myProperties;
 
    @Autowired
    public ConfigurationController(MyProperties myProperties) {this.myProperties = myProperties;}
   ...
}

在这种情况下,测试不需要任何特定的注释。

完整的 Spring 服务器测试

该测试(HttpRequestIT)使用 @SpringBootTest 进行注释,并确保使用随机端口,以防止运行测试时发生端口冲突。调用端点并验证响应。使用这些属性不需要额外的注释。

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HttpRequestIT {@Value(value="${local.server.port}")
    private int port;
 
    @Autowired
    private TestRestTemplate restTemplate;
 
    @Test
    public void configurationShouldReturnProperties() throws Exception {
        assertThat(this.restTemplate.getForObject("http://localhost:" + port + "/configuration",
                String.class)).contains("""
                Value of enabled = false
                Value of stringConfig = First piece
                Value of additional.addEnabled = false
                Value of additional.addString = First piece Second piece""");
    }
}

没有服务器测试的 Spring 应用程序上下文

此测试 (WebLayerIT) 使用 @WebMvcTest 进行注释,这意味着此测试使用有限数量的 bean 启动应用程序上下文。因此,您需要添加 

@EnableConfigurationProperties 注解才能使用这些属性。

@EnableConfigurationProperties 在配置类和测试之间创建绑定。

@WebMvcTest
@EnableConfigurationProperties(MyProperties.class)
public class WebLayerIT {
 
    @Autowired
    private MockMvc mockMvc;
 
    @Test
    public void configurationShouldReturnProperties() throws Exception {this.mockMvc.perform(get("/configuration")).andDo(print()).andExpect(status().isOk())
                .andExpect(content().string(containsString("""
                        Value of enabled = false
                        Value of stringConfig = First piece
                        Value of additional.addEnabled = false
                        Value of additional.addString = First piece Second piece""")));
    }
 
}

测试应用程序属性

上述测试使用应用程序中定义的应用程序属性。出于测试目的,通常需要使用特定于测试的应用程序属性。这些可以放在测试目录中。为了使用它们,您必须使用 @TestPropertyResource 注释。该测试 WebLayerTestPropertiesIT 与上面的测试相同 WebLayerIT,除此之外,它使用测试应用程序属性。

@WebMvcTest
@EnableConfigurationProperties(MyProperties.class)
@TestPropertySource(locations = "/application-test.properties")
public class WebLayerTestPropertiesIT {
 
    @Autowired
    private MockMvc mockMvc;
 
    @Test
    public void configurationShouldReturnProperties() throws Exception {this.mockMvc.perform(get("/configuration")).andDo(print()).andExpect(status().isOk())
                .andExpect(content().string(containsString("""
                        Value of enabled = false
                        Value of stringConfig = First test piece
                        Value of additional.addEnabled = false
                        Value of additional.addString = First test piece Second piece""")));
    }
 
}

@ConfigurationProperties + @EnableConfigurationProperties

在模块 config2 中,您将再次使用,就像在模块 config1@ConfigurationProperties 中一样,但这次没有注释。为了使用控制器中的属性,您需要添加注释。@Component@EnableConfigurationProperties

MyProperties 没有注释的类 @Component:

@Getter
@Setter
@ConfigurationProperties("my.properties")
public class MyProperties {...}

带注释的控制器 @EnableConfigurationProperties:

@RestController
@EnableConfigurationProperties(MyProperties.class)
public class ConfigurationController {
 
    private final MyProperties myProperties;
 
    @Autowired
    public ConfigurationController(MyProperties myProperties) {this.myProperties = myProperties;}
   ...
}

文章来源地址 https://www.toymoban.com/diary/java/406.html

无需 @EnableConfigurationProperties 在测试中添加该注释,因为该注释已添加到控制器中。

@ConfigurationProperties + @Component

在模块 config3 中,您将使用与模块 config1 中相同的设置,但这次使用 @Configuration 注释。@Configuration 注释创建配置构造型的 Spring bean。@EnableConfigurationProperties 注释不应与 @Configuration 注释直接一起使用,另请参阅 Andy Wilkinson 的 Stack Overflow 回答。

MyProperties 类与模块 config2 中的类相同:

@Getter
@Setter
@ConfigurationProperties("my.properties")
public class MyProperties {...}

您引入了一个新类 ApplicationConfig,它将充当配置 bean。您可以使用 @Configuration 对其进行注释。您还需要使用 @EnableConfigurationProperties 对其进行注释,以便该 bean 可以使用这些属性。

@Configuration
@EnableConfigurationProperties(MyProperties.class)
public class ApplicatonConfig {}

控制器不需要任何额外的注释:

@RestController
public class ConfigurationController {
 
    private final MyProperties myProperties;
 
    @Autowired
    public ConfigurationController(MyProperties myProperties) {this.myProperties = myProperties;}
    ...
}

测试与 config1 的测试相同,需要在 @WebMvcTest 测试中添加 @EnableConfigurationProperties 注释。

@ConfigurationProperties + @ConfigurationPropertiesScan

在模块 config4 中,您可以 @ConfigurationProperties 将属性映射到 class MyProperties。这一次,您 @ConfigurationPropertiesScan 向该类添加注释 MySpringBootConfigurationPlanetApplication,即用 注释的类 @SpringBootApplication。通过 @ConfigurationPropertiesScan 注释,您还可以指定哪些包包含配置类。

主类定义如下:

@SpringBootApplication
@ConfigurationPropertiesScan("com.mydeveloperplanet.myspringbootconfigurationplanet.config4.config")
public class MySpringBootConfigurationPlanetApplication {public static void main(String[] args) {SpringApplication.run(MySpringBootConfigurationPlanetApplication.class, args);
    }
 
}

MyProperties 类只需要 @ConfigurationProperties。

@Getter
@Setter
@ConfigurationProperties("my.properties")
public class MyProperties {...}

控制器不需要任何配置注释:

@RestController
public class ConfigurationController {
 
    private final MyProperties myProperties;
 
    @Autowired
    public ConfigurationController(MyProperties myProperties) {this.myProperties = myProperties;}
    ...
}

这些测试再次与 config1 的测试相同。

构造函数绑定

在模块 config5 中,您使用与之前的 config4 模块相同的设置。这次,您将在 MyProperties 类中使用构造函数绑定。差异是:

  • 无需指定 setter,属性可最终确定;

  • 您需要添加一个构造函数来映射配置;

  • 默认值需要通过 @DefaultValue 构造函数参数列表中的注解来指定;

  • 您可能需要使用 注释嵌套属性 @DefaultValue,否则,当嵌套属性的任何属性都没有赋值时,它们将被视为不存在。

该类 MyProperties 如下:

@Getter
@ConfigurationProperties("my.properties")
public class MyProperties {
 
    private final boolean enabled;
 
    private final String stringConfig;
 
    private final Additional additional;
 
    public MyProperties(boolean enabled, String stringConfig, @DefaultValue Additional additional) {
        this.enabled = enabled;
        this.stringConfig = stringConfig;
        this.additional = additional;
    }
 
    @Getter
    public static class Additional {
 
        private final boolean addEnabled;
 
        private final String addString;
 
        public Additional(boolean addEnabled, String addString) {
            this.addEnabled = addEnabled;
            this.addString = addString;
        }
    }
 
}

如果您 @DefaultValue 在参数列表中省略参数 additional 并将属性放入 my.properties.additional.add-string 注释 application.properties 中,您会注意到输出是:

Value of enabled = false
Value of stringConfig = First test piece

代替:

Value of enabled = false
Value of stringConfig = First test piece
Value of additional.addEnabled = false
Value of additional.addString = null

当你运行 WebLayerIT 测试时。

这些测试再次与 config1 的测试相同。

总结

有多个选项可用于在 Spring Boot 应用程序中配置属性。这篇文章试图涵盖一些选项并通过示例解释差异。构造函数绑定配置与其他选项不同,因为它不允许您在运行时修改属性。

选择哪一个?在我看来,@ConfigurationProperties + @ConfigurationPropertiesScan 或构造函数绑定是可供选择的,因为它们需要最少的注释。构造函数绑定更加安全,因为属性在运行时无法修改。但是,您应该始终根据您的用例考虑选项。

到此这篇关于 Spring Boot 配置属性解释的文章就介绍到这了, 更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持 TOY 模板网!

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于1970-01-01发表,共计9486字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)