结论
只需要修改一下pom.xml,去掉tomcat的依赖,加上jetty的依赖即可。
<dependencies>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>
启动日志如下:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.5.RELEASE)
2020-03-20 14:07:42.391 INFO 6904 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication on DESKTOP-GCV0BI2 with PID 6904 (C:\Users\Shadow\IdeaProjects\demo\target\classes started by Shadow in C:\Users\Shadow\IdeaProjects\demo)
2020-03-20 14:07:42.393 INFO 6904 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to default profiles: default
2020-03-20 14:07:42.987 INFO 6904 --- [ main] org.eclipse.jetty.util.log : Logging initialized @1500ms to org.eclipse.jetty.util.log.Slf4jLog
2020-03-20 14:07:43.053 INFO 6904 --- [ main] o.s.b.w.e.j.JettyServletWebServerFactory : Server initialized with port: 8080
2020-03-20 14:07:43.057 INFO 6904 --- [ main] org.eclipse.jetty.server.Server : jetty-9.4.26.v20200117; built: 2020-01-17T12:35:33.676Z; git: 7b38981d25d14afb4a12ff1f2596756144edf695; jvm 1.8.0_212-b10
2020-03-20 14:07:43.079 INFO 6904 --- [ main] o.e.j.s.h.ContextHandler.application : Initializing Spring embedded WebApplicationContext
2020-03-20 14:07:43.079 INFO 6904 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 631 ms
2020-03-20 14:07:43.155 INFO 6904 --- [ main] org.eclipse.jetty.server.session : DefaultSessionIdManager workerName=node0
2020-03-20 14:07:43.155 INFO 6904 --- [ main] org.eclipse.jetty.server.session : No SessionScavenger set, using defaults
2020-03-20 14:07:43.156 INFO 6904 --- [ main] org.eclipse.jetty.server.session : node0 Scavenging every 600000ms
2020-03-20 14:07:43.161 INFO 6904 --- [ main] o.e.jetty.server.handler.ContextHandler : Started o.s.b.w.e.j.JettyEmbeddedWebAppContext@8e76f1{application,/,[file:///C:/Users/Shadow/AppData/Local/Temp/jetty-docbase.1728500713783162746.8080/],AVAILABLE}
2020-03-20 14:07:43.162 INFO 6904 --- [ main] org.eclipse.jetty.server.Server : Started @1674ms
2020-03-20 14:07:43.263 INFO 6904 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-03-20 14:07:43.377 INFO 6904 --- [ main] o.e.j.s.h.ContextHandler.application : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-03-20 14:07:43.377 INFO 6904 --- [ main] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-03-20 14:07:43.381 INFO 6904 --- [ main] o.s.web.servlet.DispatcherServlet : Completed initialization in 4 ms
2020-03-20 14:07:43.400 INFO 6904 --- [ main] o.e.jetty.server.AbstractConnector : Started ServerConnector@1080f3a{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2020-03-20 14:07:43.404 INFO 6904 --- [ main] o.s.b.web.embedded.jetty.JettyWebServer : Jetty started on port(s) 8080 (http/1.1) with context path '/'
2020-03-20 14:07:43.406 INFO 6904 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 1.311 seconds (JVM running for 1.92)
分析过程
- 从main方法一路断点跟过来,进入创建服务器的方法
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
//创建获取一个服务器创建工厂
ServletWebServerFactory factory = getWebServerFactory();
//创建服务器
this.webServer = factory.getWebServer(getSelfInitializer());
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
此时栈信息为:
createWebServer:179, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
onRefresh:153, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
refresh:544, AbstractApplicationContext (org.springframework.context.support)
refresh:141, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
refresh:747, SpringApplication (org.springframework.boot)
refreshContext:397, SpringApplication (org.springframework.boot)
run:315, SpringApplication (org.springframework.boot)
run:1226, SpringApplication (org.springframework.boot)
run:1215, SpringApplication (org.springframework.boot)
main:12, DemoApplication (com.example.demo)
- 查看方法 getWebServerFactory,发现是在Spring容器中存在一个类型为ServletWebServerFactory的Bean,必须有且只有唯一一个。
protected ServletWebServerFactory getWebServerFactory() {
// Use bean names so that we don't consider the hierarchy
String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
if (beanNames.length == 0) {
throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing "
+ "ServletWebServerFactory bean.");
}
if (beanNames.length > 1) {
throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple "
+ "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
}
return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
}
- 通过IDEA的查找Bean的功能,可以很轻易的找到类 ServletWebServerFactoryConfiguration,
这个类里面有三个内部类,EmbeddedTomcat,EmbeddedJetty,EmbeddedUndertow。并且只有EmbeddedTomcat的 ConditionalOnClass注解没有标红。所以默认使用的是tomcat服务器。
- 现在我要想办法让EmbeddedTomcat的ConditionalOnClass标红,让EmbeddedJetty不红。使用IDEA插件maven-helper里面找tomcat的依赖。明显所有的tomcat依赖是spring-boot-starter-tomcat引入的,所以我要在spring-boot-starter-web 中去除spring-boot-starter-tomcat。
一键去除依赖。
- 引入Jetty的依赖
盲猜依赖名字为:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
- 此时查看配置类:ServletWebServerFactoryConfiguration,发现EmbeddedTomcat红了,EmbeddedJetty亮了。
- 搞完收工