java - SpringBootServletInitializer 和 @ConfigurationProperties 不适用于 .war 部署上的根属性

标签 java spring spring-boot

我正在使用 Spring Boot 2.0.0.RC1 构建我的 REST 服务。为了提供 jar 执行和 .war 部署,我扩展了 SpringBootServletInitializer,如下所示:

@Configuration
@SpringBootApplication
@EnableWebFlux
@EnableConfigurationProperties({ RbsConfiguration.class, 
JwtConfiguration.class })
public class RbsApplication extends SpringBootServletInitializer 
implements WebFluxConfigurer {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(RbsApplication.class, args);
    }

    ...
}

我还使用 @ConfigurationProperties 将我的 application.yml 配置绑定(bind)到这样的 bean:

@ConfigurationProperties
@Validated
public class RbsConfiguration {

    private Map<String, String> users;

    @NotEmpty
    public Map<String, String> getUsers() {
        return users;
    }

    public void setUsers(Map<String, String> users) {
        this.users = users;
    }
}

使用此application.yml:

users:
  user1:
    password: secret

当我使用 java -jar 启动应用程序时,一切都会按预期工作,并且我可以通过 RbsConfiguration 访问用户。但是如果我将其作为 .war 部署到 Tomcat,则会出现以下异常:

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to bind properties under '' to foo.bar.RbsConfiguration:

    Reason: PropertyName must not be empty

Action:

Update your application's configuration

...

Caused by: org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under '' to foo.bar.RbsConfiguration
    at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:227)
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:203)
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:187)
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:169)
    at org.springframework.boot.context.properties.ConfigurationPropertiesBinder.bind(ConfigurationPropertiesBinder.java:79)
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:167)
    ... 100 more
Caused by: java.lang.IllegalArgumentException: PropertyName must not be empty
    at org.springframework.util.Assert.hasLength(Assert.java:233)
    at org.springframework.boot.origin.PropertySourceOrigin.<init>(PropertySourceOrigin.java:41)
    at org.springframework.boot.origin.PropertySourceOrigin.get(PropertySourceOrigin.java:79)
    at org.springframework.boot.context.properties.source.SpringConfigurationPropertySource.find(SpringConfigurationPropertySource.java:121)
    at org.springframework.boot.context.properties.source.SpringConfigurationPropertySource.find(SpringConfigurationPropertySource.java:104)
    at org.springframework.boot.context.properties.source.SpringConfigurationPropertySource.getConfigurationProperty(SpringConfigurationPropertySource.java:86)
    at org.springframework.boot.context.properties.bind.Binder.lambda$findProperty$3(Binder.java:294)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.Spliterators$IteratorSpliterator.tryAdvance(Spliterators.java:1812)
    at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
    at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464)
    at org.springframework.boot.context.properties.bind.Binder.findProperty(Binder.java:295)
    at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:239)
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:198)
    ... 104 more

所以我想知道这里有什么区别。看起来当作为 .war 启动时,它需要一个前缀,当直接通过 Spring Boot 启动时,可以不加前缀。除了 RbsConfiguration 之外,我还有其他配置类(例如 JwtConfiguration),它们使用前缀并且似乎可以很好地与 .war 部署配合使用。

有什么提示我为什么会看到这种行为吗?

最佳答案

扩展SpringBootServletInitializer最终对我来说没有成功。它没有正确绑定(bind)根属性(我认为它甚至没有加载 application.yml),并且它以某种方式忽略了我的 Spring Security 设置并提出了自己的默认设置。

对我有用的是删除 RbsApplication 中的 extends 并简单地自己提供一个 Webflux 初始化程序,手动设置 SpringBoot 应用程序 - 很大程度上受到 SpringBootServletInitializer 的启发.

public class WebfluxInitializer extends AbstractReactiveWebInitializer {

    private ServletContext servletContext;

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        this.servletContext = servletContext;
        super.onStartup(servletContext);
    }

    @Override
    protected ApplicationContext createApplicationContext() {

        SpringApplicationBuilder builder = new SpringApplicationBuilder();

        StandardServletEnvironment environment = new StandardServletEnvironment();
        environment.initPropertySources(servletContext, null);

        builder.environment(environment);
        builder.sources(getConfigClasses());
        builder.web(WebApplicationType.NONE);
        builder.main(RbsApplication.class);

        return builder.build().run();
    }

    @Override
    protected Class<?>[] getConfigClasses() {
        return new Class[] { RbsApplication.class };
    }
}

有了这个,Webflux 和安全性按照定义工作,并且将根属性绑定(bind)到 RbsConfiguration 也可以在 .war 部署中工作。

我希望这可以帮助任何遇到类似问题的人(提供 .war 混合并尝试正确绑定(bind)根属性)。

如果有人找到更简单的方法来完成此任务,我将不胜感激!

关于java - SpringBootServletInitializer 和 @ConfigurationProperties 不适用于 .war 部署上的根属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48830050/

相关文章:

Java ShutDownHook 在 Windows 上未触发

java - 如何在没有 HibernateTemplate 的情况下轻松找到ByExample(对象实例)?

java - 如何解决: java. lang.NoSuchMethodError : javax. persistence.EntityManager.createStoredProcedureQuery(Ljava/lang/String;)

spring-boot - 如何在Spring-boot中添加静态Web内容

mysql - 一夜之间失去连接(spring boot + mysql)

java - 我怎样才能改变这个java代码,以便它再次询问密码是否无效?

java - Spring Boot JPA hibernate : No identifier specified for entity error even when @Id is present in the entity class

java - 如何使用 crawler4j 进行抓取?

java - @ConfigurationProperties 注解的警告

java - 如何在其他服务实现中从 Spring Security 接收经过身份验证的用户,而不是匿名用户。(Spring Security+JWT)