(一)问题分析
内嵌tomcat的入口类是org.apache.catalina.core.StandardService
最终找到org.springframework.context.support.AbstractApplicationContext
定位方法refresh()
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
debug可以正常进入,然后就看到我们希望看到的 ex了,即可根据问题进行解决
(二)根本原因解析
问题:为什么程序没有像以前一样,抛出错误信息???
分析:
Tomcat使用Commons-logging作为日志框架,而Springboot使用SLF4J作为日志框架(具体实现是Logback),但是问题是Commons-logging并没有logback的实现!
根据maven依赖,我们看到log4j和logback的包都被引入了,然后tomcat之能选择的是log4j,springboot使用的是logback。 log4j和logback只见缺少一个桥梁,正是缺少的这个桥梁,导致springboot只能输出logback!!!
中间的桥梁就是下面这个依赖:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>
这个依赖可以将log4j输出到slf4j,从而从sl4j(Logback)输出。
第一种解决方式:根据日志定位问题,然后采用加法处理,增加jcl-over-slf4j,打通slf4j和common-logs通道
第二种解决方式:解决冲突,一山不容二虎,排除掉slf4j,common-logs任意一方,spring使用slf4j,那可以排除调common-logs
从项目优化的角度看,第二种更优,可以减少不必要的依赖。
详情参见spring boot 2 内嵌Tomcat 抛出异常 “Stopping service [Tomcat]”