Spring Boot 1.5验证了ConfigurationProperties

时间:2017-04-18 14:17:47

标签: spring-boot

跳到最底层,了解这个问题的动机和解决方案!

在从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.propertiesdemo.prop=${profile.prop}

application-demo.propertiesprofile.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提供完整的应用程序(包括一个测试用例,显示在profile.prop中定义config/application.properties也失败了@validated但在没有成功的情况下成功。

我想这是Spring Boot中的一个错误,但是我可能不会理解某些内容,所以首先是SoF(正如Spring Boot在github上发布的经理所示)。

这个github问题似乎有关:https://github.com/spring-projects/spring-boot/issues/8173

1 个答案:

答案 0 :(得分:1)

当我找到我的问题的解决方案时(前段时间已经提到,但在问题本身中作为解释添加),我认为在这里复制我的发现可能更有帮助。

我的示例代码的问题是@Validated使用代理包装真实类,因此可以注入验证问题,因此返回properties.prop == null ? "null" : properties.prop;实际上是尝试访问prop代理领域。更改为getProp()是修复。一旦发现就很明显了。

关于生产代码:问题与https://github.com/spring-projects/spring-boot/issues/8173有关,或者更确切地说与https://github.com/spring-cloud/spring-cloud-commons/issues/177有关,因为我们使用的是spring-cloud。基本上,BeanPostProcessorspring-cloud之间的spring-boot之间存在冲突(github上的票证中的详细信息),Dalston.RELEASE spring-cloud解决了此问题。只是更新我们项目中的依赖项也解决了生产中的问题。很多挖掘和测试只是在我们的代码库中更改了7个字符。