问题描述
spring boot项目需要打包为war包,按照官网的操作:
- 启动类继承SpringBootServletInitializer类
- maven的pom文件将自带的tomcat设置为provided(这个的意思就是:被依赖项目理论上可以参与编译、测试、运行等阶段,相当于compile,但是再打包阶段做了exclude的动作)
public class AasWebApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(AasWebApplication.class);
}
static {
HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);
}
public static void main(String[] args){
SpringApplication.run(AasWebApplication.class,args);
}
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
在做了这两个操作之后,打包成war包是没有问题,但是本地运行spring boot项目的时候报错了,最主要的错误信息是:Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:155)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:540)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
at com.xc.AasWebApplication.main(AasWebApplication.java:33)
Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:204)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:178)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:152)
... 8 common frames omitted
问题定位
按照错误日志,一步步debug
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
// 第一次会获取webServerFactory
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();
}
protected ServletWebServerFactory getWebServerFactory() {
// Use bean names so that we don't consider the hierarchy
String[] beanNames = getBeanFactory()
.getBeanNamesForType(ServletWebServerFactory.class);
if (beanNames.length == 0) {
// 错误主要是这里抛出的,也就是没有初始化ServletWebServerFactory这个类
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);
}
具体spring boot怎么初始化tomcat的,请搜索其他资料。我们主要用到的是这个类TomcatServletWebServerFactory
image-20200518185508165.png看到这边我们就大概可以定位到问题了,就是TomcatServletWebServerFactory这个类没有被初始化。
问题解决
所以思考下我们做了什么操作?我们将tomcat包设置了<scope>provided</scope>
,我们本意是打包的时候才不需要将这个包加入lib里面,正常调试编译是可以编译到的,那么可不可能是编译器的问题呢?
我们打开idea运行时的配置Run=>Edit configurations
image-20200518190240842.png好了,看到这里,问题就知道怎么解决了,原先这个没打勾,也就是运行的时候,不会将<scope>provided</scope>
的包加入编译,我们将这个打钩,重新运行一下,问题就解决了。
这个参数跟idea版本有关系,在下面这个版本之后就被默认打钩了。
image-20200518192028370.png
网友评论