如何在不将内部类设为配置属性的情况下验证Spring Boot内部类配置
基于Spring Boot 3.5.3的应用,使用@ConfigurationProperties配合静态内部类建模子配置。此前内部类无需添加@ConfigurationProperties即可按字段名正确绑定值,但添加@Validated、@Min等验证注解后,内部类的验证完全不生效,只有给内部类本身加上@ConfigurationProperties时验证才会生效。
验证有效的外部类代码:
@ConfigurationProperties(prefix = "[...]", ignoreUnknownFields = false) @Validated @Value public class AuthCfgProps { @Min(3) int dummy; }
验证无效的内部类(需添加@ConfigurationProperties才生效):
//@ConfigurationProperties(prefix = "[...]", ignoreUnknownFields = false) @Validated @Value static class TokenTtl { @Min(2) int number; @NotNull ChronoUnit unit; @NonNull Duration toDuration() { return Duration.of(number, unit); } }
此外,存在被多个属性共享的内部类,无法设置统一的配置前缀:
@NotNull BackendsCfgProps.Instance field1; @NotNull BackendsCfgProps.Instance field2; @NotNull BackendsCfgProps.Instance field3;
@AllArgsConstructor(access = AccessLevel.PACKAGE) // Reduced visibility, because only used by Spring. @ConfigurationProperties(prefix = "veda.cloud.gateway-lib.backends.field1?", ignoreUnknownFields = false) @Validated @Value public static class Instance { @NotNull Credentials credentials; boolean enabled; @NotBlank URI urlBase; }
需求:无需将内部类设为配置属性,实现对其的验证。
无需给内部类添加@ConfigurationProperties,只需通过以下方式实现嵌套类的验证:
在父类的嵌套类字段上添加
@Valid注解:
当父类被@Validated标记时,@Valid会触发对嵌套对象的递归验证,内部类的验证注解即可生效,无需给内部类额外配置@ConfigurationProperties或@Validated。示例修改后的
AuthCfgProps:@ConfigurationProperties(prefix = "[...]", ignoreUnknownFields = false) @Validated @Value public class AuthCfgProps { @Min(3) int dummy; // 给内部类字段添加@Valid @Valid TokenTtl tokenTtl; // 内部类无需@ConfigurationProperties和@Validated @Value static class TokenTtl { @Min(2) int number; @NotNull ChronoUnit unit; @NonNull Duration toDuration() { return Duration.of(number, unit); } } }共享内部类的验证处理:
对于被多个字段共享的Instance内部类,在每个引用该类的字段上添加@Valid即可,无需给Instance类添加@ConfigurationProperties:@ConfigurationProperties(prefix = "veda.cloud.gateway-lib.backends", ignoreUnknownFields = false) @Validated @Value public class BackendsCfgProps { @NotNull @Valid Instance field1; @NotNull @Valid Instance field2; @NotNull @Valid Instance field3; @AllArgsConstructor(access = AccessLevel.PACKAGE) @Value public static class Instance { @NotNull @Valid // 如果Credentials也是嵌套类,需加@Valid触发递归验证 Credentials credentials; boolean enabled; @NotBlank URI urlBase; } }确保验证依赖和自动配置生效:
项目中需引入spring-boot-starter-validation依赖(Spring Boot 3.x默认不包含该依赖),确保验证相关Bean被自动配置:<!-- Maven依赖示例 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
原理:@Validated标记需要验证的配置类,@Valid触发嵌套对象的递归验证,Spring Boot配置属性绑定完成后,会根据这两个注解的标记执行完整的验证流程,无需给嵌套类单独配置@ConfigurationProperties。
内容的提问来源于stack exchange,提问作者Thorsten Schöning

