软件版本:
idea:2019.1 ultimate
springboot: 2.2.5
tomcat:9.0.31
一、修改默认打包方式,讲打包方式改为war
<version>0.0.1-SNAPSHOT</version>
<name>infocollection</name>
<description>Demo project for Spring Boot</description>
<!--在打包到生产环境Tomcat时指明打包方式-->
<packaging>war</packaging>
二、排除springboot内置的tomcat的容器
为什么要排除springboot内置tomcat呢?
因为如果不排除内置的tomcat,当我们打成war包发布到生产环境的tomcat时,就会出现两个tomcat冲突的问题。为了避免不必要的麻烦,所以这里排除内置的tomcat。
这里有两种方式可供选择:
- 使用
<exclusion>
标签,排除springboot中的内置tomcat:
<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>
- 添加tomcat依赖,并设置
<scope>
为provided
,用来覆盖springboot中的tomcat的<scope>
:
<!--当打war包到tomcat时,自动排除内置的tomcat,避免二者产生冲突-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!--打包的时候可以不用包进去,别的设施会提供。事实上该依赖理论上可以参与编译,测试,运行等周期。
相当于compile,但是打包阶段做了exclude操作-->
<scope>provided</scope>
</dependency>
这里虽然有两种方法,但是明眼人一眼就可以看出来,当然是选择第二种好一些,虽然两种操作都可以在打war包时成功吧内置tom猫排除,但是第二种操作可以在打war之后,不修改任何代码,还是可以继续修改代码,继续使用内置tomcat测试代码。所以这里墙裂推荐第二种方法。
在springboot的官方文档上也是介绍使用第二种方法。这是原话:The final step in the process is to ensure that the embedded servlet container does not interfere with the servlet container to which the war file is deployed. To do so, you need to mark the embedded servlet container dependency as being provided.
三、继承SpringBootServletInitializer类,并重写config方法
全称:org.springframework.boot.web.servlet.support.SpringBootServletInitializer,官方文档也有详细介绍为什么要继承。
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
这里亲测,继承这个类之后,只是在部署war到生产环境时告诉tomcat自己的启动入口在哪。而如果你要修改代码并用内置tomcat测试,完全是不影响的,不用将代码还原回来。
四、端口,路径:
- 我们在application.properties或者在application.yml中对tomcat配置的
port
和context-path
对war文件是不起作用的,那个配置只对springboot内置的tomcat起作用。当我们把war部署到生产环境时,端口就是生产环境的端口,context-path
就是war
的文件名,或者自己在tomcat中配置的其他名字。 - 为了防止应用上下文所导致的项目访问资源加载不到的问题,
建议pom.xml文件中<build></build>标签下添加<finalName></finalName>标签:
<build>
<!--打war包到生产环境时配置-->
<finalName>photoSystem</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
五、使用maven进行打包发布:
clean是清除之前的包,-Dmaven.test.skip=true是忽略测试代码
直接使用idea的maven插件进行打包发布:
先进行clean清除target下面的文件,然后package将war包打包到target文件夹下。或者用install将war包打包到本地仓库中就好了。
六、结果:
可以看到,这里有一个是war包,另一个是.original文件,其实这两个都是war包,把.original去掉,然后放到tomcat里面,照样可以运行。
其实他们两的区别就是,第一个war包里面的WEB-INF文件夹下有
lib
和lib-provided
文件夹,lib-provided
文件夹里面有spring中你排除的那个tomcat,所以war包也可以通过java -jar在命令行中启动。而.original中的WEB-INF下就只有lib
文件夹,没有lib-provided
文件夹。自然只能够通过tomcat来启动,而不能够通过命令行的java -jar来启动。所以我们在使用时,直接使用.war的文件就好了。
七、温馨提示:
建议springboot中的tomcat是什么版本,就在生成环境使用说明版本的tomcat,这样可以避免出现不必要的错误。
比如,现在的springboot内置的是tomcat9,而如果你把war丢到tomcat7 中运行,就会报错说找不到
el-api.jar
,这个其实不是tomcat7中没有这个jar包,而是tomcat9中的el-api.jar
版本比较高,而tomcat7中不支持。当然了,如果生产环境不允许的话,也可以把tomcat7中的lib进行调换即可。