众所周知,Spring boot中内置了tomcat,所以可以将项目直接打包成jar包后运行在内置的tomcat上。然而,有时候希望将项目打包为war包,此时往往需要排除内置的tomcat依赖。今天发现我的项目中并没有排除内置的tomcat,并且打包为war包运行在外置tomcat上,运行过程一切正常,说好的要排除内置的tomcat呢?为何即使不排除,打成的war包也能正常跑起来呢?
我决定探究一下这个反常问题出现的原因
首先,需要了解springboot内置的tomcat的scope是什么:
点开pom文件中的spring-boot-starter-web
:
点开后发现其pom中没有tomcat的依赖,但是它继承了父pom:
接着点开其父pom (spring-boot-starters
) 发现其中仍然没有tomcat依赖,但是发现了它上面还有爸爸:
点开这个爸爸,发现其中仍然没有tomcat相关依赖,好在它还有爸爸:
点开这个spring-boot-dependencies
之后,终于看到了<dependencyManagement>
标签中的tomcat依赖,显然,它的scope是 compile:
以上这些操作只为说明一件事,spring boot内置的tomcat的scope是compile范围的
有了这个信息,就能明白为何网上说如果使用外置tomcat运行需要排除spring boot内置的tomcat了 :
因为内置的tomcat是complie类型的,会被打包进war包,这样就和外置的tomcat产生冲突了
回到讨论的问题:为何有时候不排除内置tomcat仍旧可以运行呢,因为多数情况下排除内置tomcat后开发人员会重新引入一个provided类型的tomcat依赖(这样首先是不会打包进war包从而引发jar包冲突)来作为测试使用,根据maven的最短路径优先原则,如果这个用户引入的tomcat依赖比内置的tomcat的依赖路径短,则会替代内置tomcat,相当于已经自动排除了内置tomat了(我这里就是这个情况)。 显然,如果用户即没排除内置tomcat也没主动引入provided类型的tomcat,则注定要产生jar包冲突
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
说白了就一句话,我的项目中主动引入了scope为provided的tomcat作为测试使用,所以maven的最短路径优先原则已经自动将spring boot内置tomcat排除了,所以没有手动排除也能正常运行;然而,未必每次都那么幸运(用户引入的tomcat依赖路径比内置tomcat还长),所以习惯性将内置tomcat排除
然而,为了保险起见(未必每次都是用户自己引入的tomcat路径更短),习惯性排除内置tomcat