Spring Boot 在 Tomcat 8.5.x 但不在 8.0.37 上运行 java.lang.NoClassDefFoundError: org/apache/coyote/UpgradeP
Posted
技术标签:
【中文标题】Spring Boot 在 Tomcat 8.5.x 但不在 8.0.37 上运行 java.lang.NoClassDefFoundError: org/apache/coyote/UpgradeProtocol【英文标题】:Spring Boot Runs on Tomcat 8.5.x but not 8.0.37 java.lang.NoClassDefFoundError: org/apache/coyote/UpgradeProtocol 【发布时间】:2019-06-12 04:38:46 【问题描述】:对 Spring 来说相对较新,所以我猜我没有正确地做某事。我一直在将较旧的 java soap 服务转换为 spring。我可以在 tomcat 8.5 及更高版本上本地运行它,但是当我在 tomcat 8.0.37 上运行它时(这是我将部署它的服务器),我收到以下错误。我在另一个项目中遇到了这个错误,但在另一个项目中意识到我不必要地创建了一个 servlet,所以一旦我删除了 servlet 代码,我就可以开始了。在这种情况下,我需要创建一个 servlet。该错误正在寻找不在 Tomcat 8.0.37 中的“org/apache/coyote/UpgradeProtocol”。不确定我的代码中有什么正在尝试使用它。任何建议都非常感谢,谢谢。
pom 中的 Tomcat 依赖项...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.7.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
错误...
2019-01-17 16:05:12,539 SEVERE Class= org.apache.catalina.core.ContainerBase Method= addChildInternal Message= ContainerBase.addChild: start: org.apache.catalina.LifecycleException:无法启动组件 [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/exampleServices]] 在 org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:162) 在 org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725) 在 org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701) 在 org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717) 在 org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:940) 在 org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1816) 在 java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) 在 java.util.concurrent.FutureTask.run(FutureTask.java:266) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 在 java.lang.Thread.run(Thread.java:745) 原因:org.springframework.beans.factory.BeanCreationException:在类路径资源[com/removed/exampleServices/exampleServicesConfiguration.class]中定义名称为“containerFactory”的bean创建错误:通过工厂方法实例化bean失败;嵌套异常是 org.springframework.beans.BeanInstantiationException:无法实例化 [org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory]:工厂方法 'containerFactory' 抛出异常;嵌套异常是 java.lang.NoClassDefFoundError: org/apache/coyote/UpgradeProtocol 在 org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:591) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1246) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1096) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:535) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495) 在 org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:548) 在 org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) 在 org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) 在 org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:386) 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:307) 在 org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:157) 在 org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:137) 在 org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:91) 在 org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:172) 在 org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5303) 在 org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
下面的配置类,我认为问题在于我如何创建我的 TomcatServletWebServerFactory 或我的 ServletRegistrationBean
@ComponentScan("com.example.exampleservices", "com.example.examplesoapservices")
@Configuration
@EnableAWSF
public class exampleservicesConfiguration
static
// Statically initialize SystemImpl so it doesn't slow down first
// request
try
SystemImpl.getInstance();
catch (exampleException e)
throw new RuntimeException(e);
@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext)
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new WSSpringServlet(), "/exampleservicesSOAP/*", "/exampleservicesSOAPV3/*");
//ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new WSSpringServlet(), "/exampleservicesPort/*", "/exampleservicesPortV3/*");
servletRegistrationBean.setEnabled(true);
servletRegistrationBean.setLoadOnStartup(0);
return servletRegistrationBean;
@Bean
@SneakyThrows
public SpringBinding springBinding(exampleservicesSOAPImpl exampleservicesSOAPImpl, AWSFHandlers awsfHandlers) throws Exception
SpringBinding springBinding = new SpringBinding();
springBinding.setUrl("/exampleservicesSOAP");
SpringService springService = new SpringService();
springService.setBean(exampleservicesSOAPImpl);
springService.setHandlers(awsfHandlers.getAwsfHandlers());
springBinding.setService(springService.getObject());
return springBinding;
@Bean
@SneakyThrows
public SpringBinding springBindingV3(exampleservicesSOAPV3Impl exampleservicesSOAPV3Impl, AWSFHandlers awsfHandlers) throws Exception
SpringBinding springBinding = new SpringBinding();
springBinding.setUrl("/exampleservicesSOAPV3");
SpringService springService = new SpringService();
springService.setBean(exampleservicesSOAPV3Impl);
springService.setHandlers(awsfHandlers.getAwsfHandlers());
springBinding.setService(springService.getObject());
return springBinding;
@Bean
public Executor threadPoolTaskExecutor()
return new ThreadPoolTaskExecutor();
@Bean
public TomcatServletWebServerFactory containerFactory()
return new TomcatServletWebServerFactory ()
protected void customizeConnector(Connector connector)
super.customizeConnector(connector);
;
@Bean
public Jaxb2Marshaller jaxb2Marshaller()
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setContextPath(exJAXBContext.JAXB_CONTEXT_PATH);
return jaxb2Marshaller;
@Bean
private static JAXBContext initContext()
try
return JAXBContext.newInstance(BasicServiceComponents.eesvcof.getClass().getPackage().getName() + ":" + BasicServiceComponents.eesvcofV3.getClass().getPackage().getName());
catch (JAXBException e)
e.printStackTrace();
return null;
private static final JAXBContext context = initContext();
@Bean
public Marshaller marshaller()
Marshaller marshaller = null;
try
marshaller = this.context.createMarshaller();
catch (JAXBException e)
// TODO Auto-generated catch block
e.printStackTrace();
//any setters
return marshaller;
@Bean
public Unmarshaller unmarshaller()
Unmarshaller unmarshaller = null;
try
unmarshaller = this.context.createUnmarshaller();
catch (JAXBException e)
// TODO Auto-generated catch block
e.printStackTrace();
//any setters
return unmarshaller;
【问题讨论】:
【参考方案1】:嗯,很可能是因为 Spring Boot 2.0 系列需要 release note 中提到的 Tomcat 8.5。 UpgradeProtocol
与 HTTP2 相关,在 Tomcat 8.0 中不存在,所以最好的办法是尝试在 application.properties 中禁用 HTTP2:
server.http2.enabled=false
【讨论】:
【参考方案2】:所以被破坏的代码是
@Bean
public TomcatServletWebServerFactory containerFactory()
return new TomcatServletWebServerFactory ()
protected void customizeConnector(Connector connector)
super.customizeConnector(connector);
;
当我在评论之前进行测试时,当我在本地运行时,我会得到一个不同的错误。与我一起工作的人建议删除这个 bean(我猜 spring 2 不需要它),并且还删除了我指定 tomcat 版本的 pom 代码。这行得通。所以本地春天正在管理我的Tomcat版本。我相信 spring 将 Tomcat 设置为 8.5.35 以用于 spring 2.0.7 版本。当我部署我的代码时,它现在在 Tomcat 8.0.35 上运行良好。所以你不需要那个bean,在本地运行时让spring设置你自己的Tomcat版本。我不确定为什么该 bean 可以在 Tomcat 8.5.35 上运行,但无论如何我都不需要它。
【讨论】:
以上是关于Spring Boot 在 Tomcat 8.5.x 但不在 8.0.37 上运行 java.lang.NoClassDefFoundError: org/apache/coyote/UpgradeP的主要内容,如果未能解决你的问题,请参考以下文章
如何更改现有 Spring Boot 应用程序中的嵌入式 tomcat 版本?
Spring Boot 打war包并利用docBase指定根目录为打包的工程