本博客参考的所有文章均已在结尾声明!!!
在 Spring Boot 项目中,有两种常见的部署方式:
1、使用 Spring Boot 自带的 内置 Tomcat,将项目打包为 jar 并直接运行。
2、使用 外置 Tomcat,将项目打包为 war 并部署到传统的 Tomcat 服务器中。
本文将从这两种方式的基础配置到实际部署,逐步展示 Spring Boot 项目如何通过内置和外置 Tomcat 实现部署。
文章目录
- 前言
- Tomcat简介
- 起源
- 作用
- 优点
- 建议
- 一、使用内置 Tomcat 打包为 Jar 部署
- 1.1 什么是内置 Tomcat 部署?
- 1.2 Jar 部署的优势
- 1.3 Jar 部署步骤
- 1.3.1 项目结构
- 1.3.2 确保pom.xml 中的依赖支持打包为 Jar
- 1.3.3 打包
- 第一种方式
- 第二种方式
- 1.3.4 运行 Jar 文件
- 1.3.5 访问接口
- 1.3.6 配置端口和其他参数
- 二、使用外置 Tomcat 打包为 War 部署
- 2.1 什么是外置 Tomcat 部署?
- 2.2 War 部署的优势
- 2.3 War 部署步骤
- 2.3.1 更改入口类
- 2.3.2 配置pom.xml文件
- (1)修改打包方式
- (2)添加依赖
- (3)移除spring boot内嵌的tomcat
- (4)一个提醒
- 2.3.3 打包
- 2.3.4 配置本地tomcat
- (1)目录介绍
- (2)修改端口
- (3)修改用户名和密码
- (4)拷贝war包
- (5)运行
- (6)Windows配置Tomcat开机自启动(非必须,根据自己情况)
- 2.3.5 tomcat部署多个web项目
- 结尾的话
- 参考文章
前言
Tomcat简介
Tomcat 是一个非常流行的 轻量级 Web 服务器,它用来运行用 Java 语言编写的 Web 应用程序。Tomcat 就像一个“中间人”或“服务员”,负责接收用户的请求,然后把这些请求转给后台的 Java 程序,处理完后再把结果返回给用户。它和传统的 Web 服务器(比如 Apache HTTP Server、Nginx)不同,Tomcat 主要是为动态 Web 应用服务的。
起源
Tomcat 的起源可以追溯到 1999 年,由 Apache 软件基金会(一个非盈利组织,负责很多开源项目)开发出来。它最早是 Java Servlet 和 JavaServer Pages (JSP) 的参考实现,也就是一个帮助 Java 程序处理网页请求的标准工具。
Tomcat 之所以得名,是因为 Apache 基金会的成员觉得 “猫科动物”(像老虎、豹等)代表着敏捷、速度和轻巧,和 Tomcat 的特点非常契合。
作用
-
接收请求:当你打开一个 Java Web 应用(比如在线商店、博客网站),Tomcat 就负责接收你的请求,比如点击商品详情页面。
-
调用后台程序:Tomcat 会把这个请求交给运行在后台的 Java 程序,让它处理你的请求,比如查询商品信息。
-
返回网页内容:当后台程序处理好你的请求后,Tomcat 会把结果(比如商品详细信息的页面)返回给你的浏览器,让你能看到网页。
简而言之,Tomcat 是一个 处理 Web 请求和生成动态网页内容的服务器。
优点
-
免费开源:Tomcat 是免费的,任何人都可以下载、使用,甚至可以改进它的代码。对个人和企业来说,这都非常有吸引力。
-
轻量级:相比其他复杂的 Java 应用服务器(比如 WebSphere、WebLogic),Tomcat 非常轻量,不需要太多资源,占用的内存和 CPU 比较少。适合一些中小型的 Java Web 项目。
-
跨平台:不管你用的是 Windows、Mac 还是 Linux,Tomcat 都可以无缝运行。这意味着你可以轻松地在不同的操作系统上搭建 Web 服务。
-
支持多种 Java 技术:Tomcat 支持 Java Servlet、JSP 等 Java 技术,这些技术是开发 Java Web 应用的基础。
-
易于集成:它可以很容易地与其他流行的框架和工具(如 Spring Boot、Maven 等)进行集成,使得项目的开发和部署更加方便。
建议
阅读本文之前建议先阅读一下这篇介绍tomcat和servlet的文章 Tomcat工作原理详细介绍,他能让你对自己即将使用的技术有一个整体的、清晰的、初步的认识。(这一篇是我阅读大量文章后筛选出的最好的了。)
我还建议大家先去学习(复习)一下maven:超级详细的 Maven 教程(基础+高级),因为将springboot部署到tomcat时会涉及到大量关于maven中依赖、标签、构建等等知识。(这一篇同样也是我认为介绍maven最好的了。)
一、使用内置 Tomcat 打包为 Jar 部署
1.1 什么是内置 Tomcat 部署?
Spring Boot 默认内置了 Tomcat 服务器,在开发和生产环境中可以直接使用。打包时,将 Tomcat 与项目代码一起打包成一个可执行的 jar 文件,然后通过命令直接运行该 jar 文件来启动服务器。
springboot默认使用tomcat作为内嵌的servlet容器,我们可以由以下步骤验证得知:
首先在自己的springboot项目中的pom.xml文件中找到下面这一条依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
ctrl+鼠标左键 点击spring-boot-starter-web,如图:
我们便会进入到spring-boot-starter-web这一jar包的pom文件中
我们可以看到,spring-boot-starter-web这一jar包已经引入了如下这一条依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>3.1.3</version>
<scope>compile</scope>
</dependency>
根据依赖的传递性,可知,我们的springboot项目已经默认使用tomcat作为内嵌的servlet容器。
当然我们也可以使用其他容器,比如使用Jetty作为Springboot的内置容器:
在我们的springboot项目中的pom.xml文件做出如下修改:
<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>
在上面的代码中,我们排除了spring-boot-starter-web默认引入的tomcat,而手动引入了jetty。
1.2 Jar 部署的优势
- 简单直接:无需安装额外的 Tomcat 服务器。
- 开发方便:在开发阶段可以通过内置的 Tomcat 快速启动和调试。
- 跨平台性:只需确保系统上有正确版本的 JDK,jar 文件在不同的环境中都可以轻松运行。
1.3 Jar 部署步骤
1.3.1 项目结构
确保项目是标准的 Spring Boot 项目,默认情况下生成的就是 jar 包。项目结构如下:
src
├─ main
│ ├─ java
│ ├─ resources
└─ test
pom.xml
1.3.2 确保pom.xml 中的依赖支持打包为 Jar
在 pom.xml 文件中,确保添加了以下插件配置,以支持打包为 jar:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
1.3.3 打包
第一种方式
使用IDEA中的maven管理,运行packsge,打成jar包
第二种方式
运行以下命令:
mvn clean package
运行后便会打包成jar包
两种方式本质上是一样的。
打包完之后我们项目的target目录下面就会多出现两个包,如图所示:
其中的.jar
包是我们需要的,那么.jar.original
包是什么呢?
简单介绍如下,详细可见后面这篇博客 springboot项目用maven打包生成的.jar.original是什么?
.jar.original 是普通jar包,不包含依赖
.jar 是可执行jar包,包含了pom中的所有依赖,可以直接用java -jar命令执行
如果是部署,就用.jar
如果是给别的项目用,就要给.jar.original这个包
1.3.4 运行 Jar 文件
生成的 jar 文件包含了内置的 Tomcat,进入cmd,运行java -jar + jar包名
springboot项目已成功启动,我们可以正常访问后端接口。
注:如果想要关闭项目,直接关闭这个cmd黑窗口就可以了
1.3.5 访问接口
使用postman测试接口,成功
在浏览器输入网址访问,成功
1.3.6 配置端口和其他参数
如果需要自定义 Tomcat 的端口、编码或其他配置,可以在 application.properties 或 application.yml 中进行配置:
server.port=9090
server.servlet.context-path=/myapp
通过这种方式,可以直接修改应用的启动参数和服务器配置。
clean清除构建结果,compile重新编译,package重新打包
重新运行
可见,访问接口的方式已经发生了变化。
二、使用外置 Tomcat 打包为 War 部署
2.1 什么是外置 Tomcat 部署?
在一些企业环境中,常常需要将 Spring Boot 项目打包为 war 文件并部署到现有的 Tomcat 服务器中。这种方式比较符合传统的 Java Web 项目部署方式。
2.2 War 部署的优势
兼容传统项目:如果项目需要在同一个 Tomcat 上运行多个应用,使用 war 部署更符合规范。
灵活配置:可以在 Tomcat 服务器层面配置资源池、连接器等,使多个项目共用。
2.3 War 部署步骤
2.3.1 更改入口类
入口类要继承SpringBootServletInitializer并重写configure方法
我们先找到springboot的入口类,在我的项目中位置在这里,大家可以仿照此去找到自己的入口类。(入口类名中一定有“~Application”)springbootstudy\src\main\java\org\example\springbootstudy\SpringbootstudyApplication.java
大家按照自己的入口类名修改,不要照搬。由于我的项目没用到数据库,所以(exclude = {DataSourceAutoConfiguration.class}) // 暂时禁用数据库
禁用了,大家不要在意。
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) // 暂时禁用数据库
public class SpringbootstudyApplication extends SpringBootServletInitializer {
//继承SpringBootServletInitializer 重写 configure
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder){
return builder.sources(SpringbootstudyApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SpringbootstudyApplication.class, args);
}
}
2.3.2 配置pom.xml文件
(1)修改打包方式
先让IDEA知道你这次要打包成war包,在pom.xml中设置打包方式 默认为jar 需要修改为war
<packaging>war</packaging>
如果你在自己的pom.xml文件中找不到标签,那么你可以自己添加,位置可以参考我的
(2)添加依赖
由于 SpringBootServletInitializer 类需要用到 servlet-api 的相关 jar 包,所以需要添加依赖。
注意这里有坑位
如果你的项目是springboot2.X
的,那就使用下面的依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version><!--版本号改成你自己适用的-->
<scope>provided</scope><!-- 使用 provided 作用域,因为外部容器会提供 Servlet API -->
</dependency>
如果你的项目是springboot3.X
的,那就使用下面的依赖
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
<scope>provided</scope> <!-- 使用 provided 作用域,因为外部容器会提供 Servlet API -->
</dependency>
因为 Spring Boot 3.x,需要确保你的所有依赖库(如 Servlet、JPA 等)都使用 Jakarta EE 规范。
而 Spring Boot 2.x,则需要确保你的所有依赖库使用Java EE (javax) 规范。
还有一点需要注意的是我们引入依赖的作用范围是<scope>provided</scope>
,这一点后面我们会解释。
(3)移除spring boot内嵌的tomcat
第一种方式(推荐):
在pom.xml文件中添加如下依赖
<!--设置此包运行时不可用-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<scope>provided</scope>
这个配置项非常重要,它的作用是 指定作用范围。provided 意味着这个依赖会在开发、编译和测试环境中存在,但不会被打包到最终的 war 文件中(因为外部运行环境中已经有Tomcat 服务器,所以不需要在项目中再嵌入)。
第二种移除方式:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
将上面这段用下面这段替换掉
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!--排除内置tomcat jar包-->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
注意如果使用了这种方式,那么在开发、测试、编译环境中我们也移除了内置的tomcat服务器,我们的springboot项目就不可以在开发环境(IDEA)中运行了
运行时会提示报错
这是因为排除内置的 Tomcat 依赖后,Spring Boot 会认为你不再使用嵌入式的 Web容器(比如 Tomcat、Jetty 等),而是打算将应用部署到外部容器(如外部 Tomcat)。这会导致 Spring Boot 不再自动配置嵌入式的 Web 容器,因此你的应用在 IDEA 中无法启动,因为没有配置 ServletWebServerFactory 这个内置的 Servlet 容器工厂。springboot项目在IDEA 中运行时是需要嵌入式的 Web 容器的。
这时我猜细心的同学会问了,我们在(2)中不是引入了servlet-api
这个依赖吗,这个的意思难道不是给我们的springboot项目引入容器?
当然不是了,servlet-api 依赖是 Servlet API 的实现,它为 Java Web 应用程序提供了处理 HTTP 请求和响应的核心功能。具体来说,Servlet 是 Java Web 应用程序的基础技术,定义了如何接收 HTTP 请求、处理业务逻辑,并返回 HTTP 响应。总的来说,它并不提供容器,而是仅提供Java Web 应用程序的核心 HTTP 处理能力。
那么我们(2)中引入的依赖为什么必须使用 provided 作用域?
当你将应用部署到外部的容器(如 Tomcat)时,容器自身已经包含了 Servlet API,如果你没有设置 provided,那么你的 WAR 文件里会重复包含这些 API,这可能会导致类冲突或者重复加载的问题。因此,provided 作用域表示依赖在编译时需要,但运行时由外部容器提供。
那么引入(2)这个依赖不是很鸡肋?用第二种移除方式本来在IDEA中就运行不了,只能在外部环境中运行,引入这个依赖的时候还设置provided作用域,打包成war包的时候根本不会把它装进去。
这么想的同学我要夸夸你了,你很细心。但是呢,我们在使用第二种移除方式的时候并不能移除这个依赖,你可以自己试一试,编译时会报错的。
如果你的项目都没办法编译,那又怎么打包呢????
jakarta.servlet-api 的作用:在编译阶段,它提供了 Servlet 类相关的 API,使得你的项目能够编译通过。
而如果你使用第一种移除方式,那你完全可以不引入(2)中的依赖。因为内置的tomcat服务器中已经包含了Servlet API,所以编译打包一点问题也没有。这也是我推荐第一种移除方式的原因
别嫌我啰嗦,我认为这正是学习、探索的过程,捋清楚思路对自己还是大有脾益的。
(4)一个提醒
2.3.3 打包
在maven中双击package
或者使用mvn clean package
命令
我们可以看到target目录下出现了.war包。
2.3.4 配置本地tomcat
如果电脑现在还没有tomcat的话,参考这篇文章下载一个【Tomcat】史上最全下载、安装配置及使用教程,(2024更新…建议收藏,教学)附Tomcat常见报错解决方法。
这里有大坑!!!
tomcat和java-jdk有很严重的兼容问题。
如果你是springboot3+jdk17,那你使用的tomcat应该是10.x
以上的。否则在访问springboot项目时会出现spring无法启动的问题,这样访问网页就会出现404
。
(1)目录介绍
我们从第一个目录开始逐个了解,只需了解其的基本用处即可。
🔖bin文件夹🌟:存放Tomcat的命令、脚本等文件,其中以.sh结尾的是Linux/MacOS系统使用命令的。以.bat结尾的则是Windows系统的命令使用的。其他的为通用项。
我们也可以在此处启动和关闭Tomcat,例如在Windows系统下,startup.bat则可以启动Tomcat,shutdown.bat则可以关闭Tomcat。
Linux和MacOS同理,它们可以运行startup.sh,shutdown.sh用来启动和关闭Tomcat。catalina.bat/catalina.sh则可以设置Tomcat的内存。🔖conf文件夹🌟:存放Tomcat的配置文件等。例如:server.xml文件可以设置端口号、域名、IP、编码等也可以将日志配置到其他目录等 。tomcat-user.xml文件则用来管理配置Tomcat的用户与权限,context.xml用来配置数据源等
🔖lib文件夹:存放Tomcat运行时所必须的JAR包文件。注意的是JAR文件只可以被Tomcat服务器所访问。
🔖logs文件夹:默认日志文件存放的目录,对于我们后期的排查起到非常重要的作用。需要注意的是,如果你是Windows系统,它将存放在以年月日命名的文件中,例如:catalina.2022-11-08.log。如果你是Linux/MacOS系统,它将存放在catalina.out文件中。
🔖temp文件夹:用来存放Tomcat的运行时的临时文件用。
🔖webapps文件夹🌟:用来存放web应用和部署项目的目录,Tomcat启动时会加载此目录下的项目应用。
在服务器上部署web项目时,只需将项目war包放入Tomcat中的webapps文件下后重启Tomcat之后war包会自动解压,此时访问项目的地址是IP+端口+项目名称就可以正常访问项目。而webapps文件夹中还有个默认的ROOT目录如下图所示:
我们同样可以将项目的war包解压后放入ROOT目录,同样可以运行该项目。需要注意的是放在ROOT目录下之后访问项目方式就会变成:IP+端口号。
而两者的区别就是放在webapps文件夹中不需要解压,放在ROOT文件夹中需要解压。放在webapps文件夹中访问项目需要加项目名 ,放在ROOT文件夹中不需要加项目名 。
我们将来启动Tomcat看到的cat页面的文件是存放在ROOT文件夹下的,如果我们将ROOT文件夹删除,再次启动Tomcat依旧会自动生成。
🔖work文件夹:存放Tomcat运行时所编译之后的文件,如需清除Tomcat缓存,可以选择清空此目录,重启Tomcat即可。
(2)修改端口
进入conf文件夹下的server.xml修改tomcat的默认启动端口
注意你设置的端口号不要被其他应用占用,否则会无法访问。
(3)修改用户名和密码
进入conf文件夹下的tomcat-users.xml修改tomcat的项目管理页面的 用户名密码及角色
添加如下几行
<!-- 定义访问管理界面的角色和用户 -->
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<!-- 定义用户并分配角色-->
<user username="admin" password="123456" roles="manager-gui,manager-script"/>
(4)拷贝war包
将springboot的war包拷贝到webapps下 ,修改war包名称 (war包名称对应项目访问路径)
例如我的war包更名为springbootstudy.war
(5)运行
在tomcat的bin目录下运行cmd
输入startup.bat
即可运行tomcat。此时,我们的springboot项目也运行了。
我们可以看到一个大大的Sping出现在窗口中,启动成功!
此时我们的webapps文件夹内多了一个springbootstudy文件夹
访问http://localhost:8080/
成功
访问http://localhost:8080/springbootstudy/rocketmq/hello
成功
至此,我们的springboot项目就部署成功了。
如果你的tomcat主页可以正常访问而项目却不能访问,如下图,那你大概率是出现了版本兼容问题。
参考这篇博客的解决方案SpringBoot项目部署在外部tomcat时运行报错404–解决方案
我的tomcat9.0.94版本和springboot3+jdk17并不兼容,我将tomcat更换到10.1.30就好了。
建议你更换tomcat版本。下面是版本对应图。
只要确认自己的环境依赖都没有错误,那么就可以考虑一下版本的兼容性,在开发中很多的bug也是版本不兼容导致的。
(6)Windows配置Tomcat开机自启动(非必须,根据自己情况)
方法很多但是意义不大,不写了。
2.3.5 tomcat部署多个web项目
可以参考这两个博客:
一个tomcat部署多个项目(同端口,多项目,不同访问路径)
多war包部署在一个tomcat中
结尾的话
阅读完本文之后可以去深入学习一下tomcat和servlet,当然时间不够的话也可以日后再学:
servlet:JavaWeb——Servlet(全网最详细教程包括Servlet源码分析)、都2023年了,Servlet还有必要学习吗?一文带你快速了解Servlet
tomcat:学习Tomcat这一篇就够了
花了很长时间终于整理完了,如果你读完觉得还不错的话,请给我点一个赞,你的支持就是我最大的动力!!!
参考文章
1、 超级详细的 Maven 教程(基础+高级) 作者:汪了个王
2、【Tomcat】史上最全下载、安装配置及使用教程,(2024更新…建议收藏,教学)附Tomcat常见报错解决方法 作者:神兽汤姆猫
3、springboot 配置tomcat部署项目 作者:fastjson_
4、SpringBoot项目部署详细步骤(jar包+war包+Tomcat下部署多个war包) 作者:bboy枫亭
5、springboot项目用maven打包生成的.jar.original是什么? 作者:清风烈酒
6、JavaWeb——Servlet(全网最详细教程包括Servlet源码分析) 作者:刘扬俊
7、springboot项目部署到 本地tomcat容器 作者:熊子不爱吃香菜
8、SpringBoot项目部署在外部tomcat时运行报错404–解决方案 作者:霖000ovo