![](/img/trans.png)
[英]Multi-context spring-boot application: how to define standard spring-boot properties for each child context
[英]Tomcat multi-context deployment stops whole process if spring-boot context fails to deploy
我有一个非常具体的 Tomcat 配置,我不想更改它,我正在为这个特定配置寻找解决方案。
我已经在 Tomcat 中的conf/server.xml文件中声明了多个上下文 ( <Context>
) 进行部署,我知道不建议这样做。 我的问题是,如果其中一个部署失败,整个 Tomcat 进程将停止,从而终止已成功启动的应用程序的 rest。 这种行为是预期的吗? 是否有属性或方法可以防止这种情况并模拟不同上下文声明的行为,类似于使用context.xml
文件?
我得到的错误如下:
ConfigServletWebServerApplicationContext:上下文初始化期间遇到异常
使用此堆栈跟踪(对于 Tomcat 版本 8.5.24):
SEVERE [Catalina-startStop-1] org.apache.catalina.core.ContainerBase.startInternal A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/auth-service]]
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:939)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/auth-service]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)
... 6 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authenticationController': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'app.client-html.context' in value "${app.client-html.context}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:405)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1415)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:608)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:326)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:173)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:153)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:95)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:174)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5196)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 6 more
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'app.client-html.context' in value "${app.client-html.context}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:178)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:175)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:931)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1308)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1287)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
... 27 more
示例配置:
<Host name="localhost" unpackWARs="true" autoDeploy="true">
<Context docBase="../../app-that-works" path="/itworks"/>
<Context docBase="../../app-that-fails" path="/itfails"/>
</Host>
重要提示:失败的应用程序是 spring-boot 应用程序,它被打包为 a.war 文件并在普通 tomcat 中运行,而不是嵌入式 tomcat 方式。 这很重要,因为这些应用程序似乎具有这种行为......
免责声明:我指的是普通 Tomcat,而不是spring 引导或嵌入式 tomcat 等。我不是在寻找这样的解决方案,只是解决这个特定问题。
基本上:
server.xml
中配置的任何组件的start
阶段(参见LifeCycle )的异常会导致服务器退出。 但是,某些异常(例如失败的ServletContextListener
)不会传播。 如果您不希望整个服务器停止,当上下文无法启动时,请使用自动部署:为server.xml
中定义的每个上下文创建文件$CATALINA_BASE/conf/<engine_name>/<host_name>/<context_path>.xml
内容:
<Context docBase="/path/to/application" />
在您的情况下,您需要创建$CATALINA_BASE/conf/Catalina/localhost/itworks.xml
和$CATALINA_BASE/conf/Catalina/localhost/itfails.xml
。 请参阅 Tomcat 对 XML 描述符的命名约定的命名。
编辑:您的堆栈跟踪表明我们可能正在处理 Tomcat 或 Spring 错误:
一方面, StandardContext
期望ServletContainerInitializer
仅抛出ServletException
(参见源代码),让所有未经检查的异常通过。 请注意,同时捕获并记录来自ServletContextListener
的所有异常(参见源代码)。
另一方面,Spring 的SpringServletContainerInitializer
可能应该将所有未经检查的异常包装到ServletException
中。
在您的情况下发生的情况是未经检查的异常一直到StandardContext
并被重新抛出为LifecycleException
停止服务器。 无论如何,设置:
<Context throwOnFailure="false" ... />
应该阻止 Tomcat 传播异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.