Spring Boot 配置属性的未解决占位符验证
Posted
技术标签:
【中文标题】Spring Boot 配置属性的未解决占位符验证【英文标题】:Unresolved Placeholder Validation for Spring Boot Configuration Properties 【发布时间】:2017-09-15 13:01:12 【问题描述】:给定一些具有不可解析占位符的应用程序配置,如以下application.yml
my:
thing: $missing-placeholder/whatever
当我使用@Value
注解时,配置文件中的占位符会被验证,所以在这种情况下:
package com.test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class PropValues
@Value("$my.thing") String thing;
public String getThing() return thing;
我收到了IllegalArgumentException: Could not resolve placeholder 'missing-placeholder' in value "$missing-placeholder/whatever"
。这是因为该值是由AbstractBeanFactory.resolveEmbeddedValue
直接设置的,没有任何东西可以捕捉到PropertyPlaceholderHelper.parseStringValue
抛出的异常
但是,希望转向 @ConfigurationProperties
样式,我注意到缺少此验证,例如在这种情况下:
package com.test;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
@ConfigurationProperties(prefix = "my")
public class Props
private String thing;
public String getThing() return thing;
public void setThing(String thing) this.thing = thing;
也不例外。我可以看到PropertySourcesPropertyValues.getEnumerableProperty
使用注释// Probably could not resolve placeholders, ignore it here
捕获异常并将无效值收集到其内部映射中。后续数据绑定不会检查未解析的占位符。
我检查了简单地将 @Validated
和 @Valid
注释应用于类和字段没有帮助。
是否有任何方法可以保留在具有ConfigurationProperties
绑定的未解析占位符上引发异常的行为?
【问题讨论】:
您应该在课堂上使用@Validated
,在现场使用@NotNull
或@NotEmpty
,并且要进行验证,您必须在类路径上使用JSR-303 验证器,例如@987654338 @。仅添加注释 @Validation
不会产生任何结果。
有人找到解决方案了吗?
【参考方案1】:
传递@Pattern
注解的正确正则表达式是^(?!\\$\\).+
@Validated
@ConfigurationProperties("my.config")
public class ConfigProperties
@Pattern(regexp = "^(?!\\$\\).+", message = "unresolved placeholder")
private String uri;
// ...
【讨论】:
【参考方案2】:显然没有更好的解决方案。至少这比 afterPropertiesSet() 更好。
@Data
@Validated // enables javax.validation JSR-303
@ConfigurationProperties("my.config")
public static class ConfigProperties
// with @ConfigurationProperties (differently than @Value) there is no exception if a placeholder is NOT RESOLVED. So manual validation is required!
@Pattern(regexp = ".*\$\.*", message = "unresolved placeholder")
private String uri;
// ...
更新:我第一次弄错了正则表达式。它匹配整个输入(不仅仅是java.util.regex.Matcher#find()
)。
【讨论】:
【参考方案3】:10 分钟前我遇到了同样的问题! 尝试在你的配置中添加这个 bean:
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer()
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setIgnoreUnresolvablePlaceholders(true);
return propertySourcesPlaceholderConfigurer;
【讨论】:
很好的发现,但实际上这是相反问题的解决方案。我不想隐藏错误,我想保留它。 您必须手动使属性类实现InitializingBean
并覆盖afterPropertiesSet()
方法,您可以通过反射检查每个字段的值并在它们为空时抛出异常。跨度>
这听起来不是很优雅,除了属性不会以 null 结尾之外,它们的占位符值仍然嵌入在字符串中。
是的,我同意,不是很优雅。如果我找到更好的方法,我会告诉你。
我不敢相信 afterPropertiesSet() 是我们拥有的最好的:'(以上是关于Spring Boot 配置属性的未解决占位符验证的主要内容,如果未能解决你的问题,请参考以下文章
带有弹簧属性占位符的 Spring Boot 和 Logback logging.config 文件
如何为具有属性依赖项的 Spring Boot Application 类编写测试用例 - 无法解析占位符