如何将@ConfigurationProperties部分属性设为必填?嵌套类是否有差异?
嘿,这个问题我熟!在Spring Boot里要让配置属性成为必填项,不管是简单类还是嵌套类都有成熟的方案,我给你拆解清楚:
一、非嵌套(简单)配置属性类实现必填
要确保env.any-property是必填项,有两种常用且可靠的方式:
方法1:构造方法绑定(Spring Boot推荐)
这种方式通过构造方法注入配置属性,直接从实例化层面强制必填,不需要额外依赖。
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConstructorBinding; @ConstructorBinding @ConfigurationProperties(prefix = "env") public class EnvProperties { private final String anyProperty; // 构造方法无可选参数,必须传入anyProperty public EnvProperties(String anyProperty) { // 手动做空值/空字符串检查,抛出明确的异常信息 if (anyProperty == null || anyProperty.isBlank()) { throw new IllegalArgumentException("配置项 env.any-property 必须设置,不能为空或空白"); } this.anyProperty = anyProperty; } // 只需要getter,不需要setter(因为是final字段) public String getAnyProperty() { return anyProperty; } }
注意:别忘了在你的主启动类或者配置类上添加@EnableConfigurationProperties(EnvProperties.class),让Spring识别这个配置类。如果启动时没配置env.any-property,Spring会因为无法实例化EnvProperties而直接抛出异常,阻止应用启动。
方法2:JSR-380校验注解
如果需要更灵活的校验规则(比如长度、格式等),可以结合@Validated和校验注解,需要先引入spring-boot-starter-validation依赖。
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.validation.annotation.Validated; import javax.validation.constraints.NotBlank; @Validated @ConfigurationProperties(prefix = "env") public class EnvProperties { @NotBlank(message = "配置项 env.any-property 为必填项,不能为空或空白") private String anyProperty; // 需要getter和setter(因为是非final字段,Spring通过setter注入) public String getAnyProperty() { return anyProperty; } public void setAnyProperty(String anyProperty) { this.anyProperty = anyProperty; } }
同样需要添加@EnableConfigurationProperties,启动时如果没配置该属性,Spring会触发校验失败,抛出BindValidationException,阻止应用启动。
二、嵌套配置属性类的必填处理
嵌套配置类的核心逻辑和简单类一致,但有一些细节需要注意,差异主要体现在嵌套属性本身是否必填的场景:
场景1:嵌套属性本身是必填项
比如父配置类app下必须有db子配置,且db内部的url、username也是必填:
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConstructorBinding; import org.springframework.validation.annotation.Validated; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @Validated @ConstructorBinding @ConfigurationProperties(prefix = "app") public class AppProperties { // 标注@NotNull确保app.db必须配置 @NotNull(message = "配置项 app.db 为必填项") @Valid // 必须添加,触发嵌套类内部的校验规则 private final DbProperties db; @NotBlank(message = "配置项 app.name 为必填项") private final String appName; // 构造方法强制传入DbProperties实例,确保必填 public AppProperties(DbProperties db, String appName) { this.db = db; this.appName = appName; } // getters public DbProperties getDb() { return db; } public String getAppName() { return appName; } // 嵌套配置类 @Validated public static class DbProperties { @NotBlank(message = "配置项 app.db.url 为必填项") private final String url; @NotBlank(message = "配置项 app.db.username 为必填项") private final String username; public DbProperties(String url, String username) { this.url = url; this.username = username; } // getters public String getUrl() { return url; } public String getUsername() { return username; } } }
场景2:嵌套属性可选,但内部属性必填
如果app.db可以不配置,但一旦配置了,内部的url、username就必须填,只需要在嵌套类内部加校验注解,父类的db属性不用加@NotNull:
@Validated @ConfigurationProperties(prefix = "app") public class AppProperties { @Valid // 仅当app.db被配置时,才校验其内部属性 private DbProperties db; @NotBlank(message = "配置项 app.name 为必填项") private String appName; // getters and setters }
嵌套类与简单类的差异总结
核心逻辑(构造方法绑定/校验注解)完全一致,但嵌套场景需要额外注意:
- 如果嵌套属性本身必填,要在父类的嵌套属性上添加
@NotNull(或@NotEmpty) - 必须添加
@Valid注解,才能触发嵌套类内部的校验规则 - 构造方法绑定在嵌套场景下依然有效,通过构造方法参数强制传入嵌套类实例,从根源上确保必填
内容的提问来源于stack exchange,提问作者John Rumpel

