【发布时间】:2017-04-18 14:17:47
【问题描述】:
跳到底部了解这个问题的动机和解决方案!
在从Spring Boot 1.4升级到1.5的过程中看了(来源:https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.5-Release-Notes#upgrading-from-spring-boot-14)
如果您有使用 JSR-303 约束注解的 @ConfigurationProperties 类,您现在应该另外使用 @Validated 对它们进行注解。现有验证当前将继续工作,但将记录警告。将来,没有@Validated 的类将根本不会被验证。
因此,我努力地将@Validated 添加到我的所有配置属性中。现在我有一个中断的特定用例,也就是不再加载属性(我先总结,然后添加代码)。
如果我使用application.properties 文件中定义的模板属性,然后尝试覆盖特定配置文件的值,则应用程序不会启动。
这里是一些重现的示例代码(相关文件):
build.gradle
buildscript {
ext {
springBootVersion = '1.5.1.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
application.properties : demo.prop=${profile.prop}
application-demo.properties:profile.prop=demo
DemoApplication.java
package package;
import javax.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@org.springframework.web.bind.annotation.RestController
public static class RestController {
@Autowired
private DemoProperties properties;
@GetMapping
public String get() {
return properties.prop == null ? "null" : properties.prop;
}
}
@Component
@ConfigurationProperties(prefix = "demo")
// @Validated
public static class DemoProperties {
@NotNull
private String prop;
public void setProp(String prop) {
this.prop = prop;
}
public String getProp() {
return prop;
}
}
}
就目前而言,我的应用程序在使用 -Dspring.profiles.active=demo 运行时会产生预期的结果
curl "http://localhost:8080"
demo
但是,取消注释 //@validated 并像以前一样运行应用程序会产生
curl "http://localhost:8080"
null
在https://github.com/ThanksForAllTheFish/boot-props 上提供完整的应用程序(包括一个测试用例,显示在config/application.properties 中定义profile.prop 与@validated 一样失败,但在没有@validated 时成功)。
我猜这是 Spring Boot 中的一个错误,但可能我没有理解某些东西,所以首先 SoF(如 github 上的 Spring Boot 问题管理器中所暗示的)。
这个 github 问题似乎相关:https://github.com/spring-projects/spring-boot/issues/8173
【问题讨论】:
-
我实际上让用例变得更加复杂。只需将 application.properties 和 demo.prop=prop 作为单行内容就足以看到相同的问题。我更新了 github 仓库
-
您没有包含验证器,因此不会验证任何内容。像这样的覆盖属性也不起作用。它不是一个多通道过程,所有内容都被读取然后处理......所以只有将它指定为系统属性、环境属性或启动参数才会使其覆盖
-
@M.Deinum,不正确,正如我所写,如果我删除
@Validated,应用程序的行为与预期一样。我也很惊讶我不需要验证器,但是如果我清空我的 application.properties 文件,我会得到一个 BindException -
(
Caused by: org.springframework.validation.BindException: org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanPropertyBindingResult: 1 errors Field error in object 'demo' on field 'prop': rejected value [null]; codes [NotNull.demo.prop,NotNull.prop,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [demo.prop,prop]; arguments []; default message [prop]]; default message [may not be null]) which imo 足以显示验证发生 -
嗯 ...显然验证器是 web starter 的默认部分(认为它是可选的)。我仍然不明白您所描述的内容有什么问题(您没有指定个人资料并且属性是
null这是正确的恕我直言,因为您没有另外指定。
标签: spring-boot