![](/img/trans.png)
[英]Error SpringBootServletInitializer after convert jar to war
[英]SpringBootServletInitializer and @ConfigurationProperties not working with root properties on .war deployments
我正在使用 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
配置绑定到这样的 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
最终对我不起作用。 它没有正确绑定根属性(我认为它甚至没有加载application.yml
)并且它以某种方式忽略了我的 Spring Security 设置并提出了自己的默认设置。
对我RbsApplication
是删除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 和安全工作定义和绑定根属性到RbsConfiguration
也在.war
部署中工作。
我希望这可以帮助任何有类似问题的人(提供 .war 混合文件并尝试正确绑定根属性)。
如果有人找到了更简单的方法来完成这项工作,我将不胜感激!
您需要在@ConfigurationProperties
定义中提供前缀。 否则,您希望事情如何运作? 一切都应该映射到您的配置类,包括spring.*
命名空间?
我猜您可能会看到这些部署之间的差异可能与启动应用程序时环境中存在的值有关。
使用 WAR 模式时,您可以从 application.yaml 加载属性:
@Bean
public PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setIgnoreResourceNotFound(true);
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
List<Resource> resources = new ArrayList<>();
resources.add(new ClassPathResource("application.yaml"));
yaml.setResources(resources.toArray(new Resource[0]));
propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
return propertySourcesPlaceholderConfigurer;
}
SpringBoot 对于 WebFlux 堆栈开箱即用不支持 WAR 模式。 使用上述方法,您可以获得并能够使用 @EnableConfigurationProperties 注释。 但它仍然是一个黑客。
关键是这个 bean 创建得太晚了,因此许多有据可查的特性 spring boot 特性不起作用。 例如属性加密(jasypt)或条件bean加载等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.