Spring Boot迁移启动失败:org.eclipse.jetty.server.Server构造方法不存在
这个问题的核心是Jetty版本与Spring Boot 2.1.x不兼容,加上你手动管理Jetty依赖、自定义Jetty Server Bean的方式和Spring Boot的自动配置机制冲突了,咱们一步步来解决:
1. 版本兼容问题:Jetty 8和Spring Boot 2.x不匹配
Spring Boot 2.1.1.RELEASE官方适配的Jetty版本是9.4.x(具体为9.4.14.v20181114),而你使用的Jetty 8.2.0是非常老旧的版本(对应Java 6/7生态),它的org.eclipse.jetty.server.Server类根本没有Spring Boot期望的(ThreadPool)构造方法——这个构造方法签名是Jetty 9.x才新增的,Jetty 8的构造方法逻辑完全不同,这就是启动报错的直接原因。
2. 修正Maven依赖:改用Spring Boot的Jetty Starter
不要手动引入jetty-server、jetty-servlet等依赖,Spring Boot的spring-boot-starter-jetty会自动帮你管理所有兼容的Jetty依赖版本,彻底避免版本冲突。修改你的pom.xml:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <!-- 引入Spring Boot官方维护的Jetty Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency>
这样Maven会自动引入所有Jetty的正确依赖版本,不需要你手动指定8.2.0.v20160908。
3. 移除自定义的Jetty Server Bean,用Spring Boot的定制方式
Spring Boot会自动创建和管理Jetty Server实例,你不需要自己定义<bean id="webServer">。如果需要定制线程池、连接器、Handler等,可以用WebServerFactoryCustomizer来实现,这是Spring Boot官方推荐的扩展方式:
@Configuration public class JettyCustomConfig { @Bean public WebServerFactoryCustomizer<JettyServletWebServerFactory> jettyServerCustomizer() { return factory -> { // 定制线程池 QueuedThreadPool threadPool = new QueuedThreadPool(); threadPool.setMinThreads(8); threadPool.setMaxThreads(32); factory.setThreadPool(threadPool); // 定制连接器(HTTP、HTTPS以及你的自定义XmlConnector) factory.addServerCustomizers(server -> { // HTTP连接器 ServerConnector httpConnector = new ServerConnector(server); httpConnector.setPort(34345); server.addConnector(httpConnector); // HTTPS连接器(配置SSL) SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath("classpath:keystore"); sslContextFactory.setKeyStorePassword("somepassword"); sslContextFactory.setKeyManagerPassword("somekeypassword"); sslContextFactory.setTrustStorePath("classpath:keystore"); sslContextFactory.setTrustStorePassword("sometrustpassword"); ServerConnector httpsConnector = new ServerConnector(server, sslContextFactory); httpsConnector.setPort(34346); server.addConnector(httpsConnector); // 你的自定义XmlConnector XmlConnector xmlConnector = new XmlConnector(server); xmlConnector.setPort(34347); server.addConnector(xmlConnector); }); // 定制Handler集合 factory.addServerCustomizers(server -> { HandlerCollection handlerCollection = new HandlerCollection(); handlerCollection.setHandlers(new Handler[]{ // 替换成你的webContexts Bean引用 contextRef, new DefaultHandler() }); server.setHandler(handlerCollection); }); // 设置关闭时不停止服务器 factory.setStopAtShutdown(false); }; } }
4. 处理自定义Server类的监听器逻辑
你原来的Server类继承了Jetty的Server并实现了ApplicationListener,现在不需要这样做了——可以单独写一个监听器Bean,通过Spring注入Spring Boot管理的Jetty Server实例:
@Component public class JettyServerEventListener implements ApplicationListener<ApplicationContextEvent> { @Autowired private JettyWebServer jettyWebServer; @Override public void onApplicationEvent(ApplicationContextEvent event) { // 获取Spring Boot管理的Jetty Server实例 org.eclipse.jetty.server.Server jettyServer = (org.eclipse.jetty.server.Server) jettyWebServer.getServer(); // 在这里实现你的监听器逻辑 } }
总结
你的问题本质是用了和Spring Boot 2.x不兼容的Jetty老版本,同时绕过了Spring Boot的自动配置机制自己管理Server实例。改用官方的Jetty Starter,使用Spring Boot推荐的定制方式,就能解决这个启动报错问题。
内容的提问来源于stack exchange,提问作者raghav

