惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tailwind CSS Blog
大猫的无限游戏
大猫的无限游戏
L
LINUX DO - 热门话题
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
雷峰网
雷峰网
aimingoo的专栏
aimingoo的专栏
博客园_首页
MongoDB | Blog
MongoDB | Blog
V
V2EX
GbyAI
GbyAI
量子位
Microsoft Azure Blog
Microsoft Azure Blog
有赞技术团队
有赞技术团队
G
Google Developers Blog
云风的 BLOG
云风的 BLOG
B
Blog
Microsoft Security Blog
Microsoft Security Blog
S
SegmentFault 最新的问题
O
OpenAI News
N
News and Events Feed by Topic
博客园 - Franky
爱范儿
爱范儿
Forbes - Security
Forbes - Security
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V2EX - 技术
V2EX - 技术
Application and Cybersecurity Blog
Application and Cybersecurity Blog
N
News and Events Feed by Topic
N
News | PayPal Newsroom
Schneier on Security
Schneier on Security
Cloudbric
Cloudbric
Security Archives - TechRepublic
Security Archives - TechRepublic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Recent Commits to openclaw:main
Recent Commits to openclaw:main
人人都是产品经理
人人都是产品经理
P
Privacy International News Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog RSS Feed
阮一峰的网络日志
阮一峰的网络日志
D
DataBreaches.Net
Last Week in AI
Last Week in AI
罗磊的独立博客
Spread Privacy
Spread Privacy
Recent Announcements
Recent Announcements
The Cloudflare Blog
Google DeepMind News
Google DeepMind News
AWS News Blog
AWS News Blog
The Register - Security
The Register - Security
Y
Y Combinator Blog
J
Java Code Geeks
I
Intezer

czp's blog

Ubuntu 下使用 zsh · HonKit 使用 VNC 来远程管理服务器 · HonKit Linux 下无限试用 JetBrains · HonKit 使用 KMS 激活 Windows · HonKit 为 KVM 中的 Windows 虚拟机启用 VirtIO · HonKit 在 Spring Boot 中处理 MissingKotlinParameterException · HonKit 用 Spring Native 拯救微服务 · HonKit 正确调试 PHP · HonKit Ubuntu 增加最大文件打开数量限制 · HonKit 将 Minecraft 服务端编译到 native · HonKit 用凝聚力购买 P 社游戏 DLC · HonKit 模拟超星网课 Android 客户端 · HonKit 模拟 Bilibili Android 客户端 · HonKit 模拟哔咔 Android 客户端 · HonKit 异步是什么 · HonKit GCP Pub/Sub push 至 IAP 保护的 Endpoint · HonKit 部署 Spring Native 到 GCP App Engine · HonKit 多个 Gradle SubProject 同时编译导致 CI/CD 内存耗尽 · HonKit Google Cloud Build 运行 DIND · HonKit 在 Google Storage 中部署 SPA · HonKit Terraform 不自动更新 CloudRun service · HonKit Telegram Bot 收不到普通群聊消息的问题 · HonKit 加密货币交易 · HonKit 挖掘以太坊 · HonKit 挖掘门罗币 · HonKit 小明学英语 · HonKit 卖程序的小女孩 · HonKit 一个测试工程师走进一家酒吧 · HonKit 我给你们讲个 TCP 笑话吧! · HonKit 我给你们讲个 UDP 笑话吧! · HonKit 格局打开 · HonKit c 语言常见未定义行为 · HonKit 在 Kotlin 使用 SpaceEngineers Remote API · HonKit Kotlin 协程 · HonKit 在 Spring Boot 中正确注册 Jackson Module · HonKit Spring Boot Jpa 使用 Google Cloud SQL · HonKit Spring Boot 中配置单页应用 · HonKit Spring Boot 无法加载 ClasspathResource 问题 · HonKit czp's blog · HonKit 鸣谢列表 · HonKit 友链 · HonKit
正确打包 Spring Boot 到 war · HonKit
2026-04-11 · via czp's blog

本文撰写时的 Spring 版本: Spring-Boot 2.0.5.RELEASE | gradle 4.10.2

众所周知, Spring Boot 在开发时之所以能直接启动, 是因为内置了 tomcat. 同时这也使得 Spring Boot 可以直接输出为可执行的 jar 文件.

那么问题来了, 如果我们需要将应用打包为 war 文件并部署到外部的 tomcat 服务器怎么办.

在 Google 搜索这个问题, 就会看到很多人跟你说, 在 gradle 里, 把 tomcat 的依赖 exclude 掉就好了. 但是这样的话, 本地调试就没法直接启动了, 既然 Spring Boot 的设计是完美的, 所以肯定不是这么弄的.

于是我们找到了 Spring Boot 文档 https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/html/#packaging-executable-wars

我们要用 providedRuntime 来标记 tomcat 的依赖, 这有什么用待会再说.

但是我们马上会发现, gradle 找不到符号 providedRuntime.

可能是文档有遗漏, 实际上我们必须先启用 war 插件(在此之前应该已经使用了 spring-boot-gradle-plugin)

apply plugin: 'war'

然后我们的依赖就变为这样

dependencies {
    // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web'
    // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-tomcat
    providedRuntime group: 'org.springframework.boot', name: 'spring-boot-starter-tomcat'
}

providedRuntime 并不会将依赖从 classpath 去除, 所以我们本地开发时依然可以直接启动.

然后我们尝试将应用打包为 war

./gradlew bootWar

注意, 执行的 gradle task 为 bootWar, 默认的 war 会被 spring-boot-gradle-plugin 跳过.

我们来看一下打包得到的 war 文件的内部结构

META-INF
    MANIFEST.MF
org
    springframework
        boot
            loader
                (Launcher)
WEB-INF
    classes
        (user code)
    lib
        (third party lib)
    lib-provided
        (tomcat)

其中的 MANIFEST.MF 与普通 jar 是一样的, 也就是说, 这个 war 可以被当做 jar 来执行, 这种 war 叫做 executable war

java -jar application-name.war

executable war 启动时, 实际上的入口类是 MANIFEST.MF 中记录的 Spring Boot Loader 类.

之后 lib-provided 目录也会被其动态加载, 所以可以正常运行.

而这个 executable war 同时也确实是一个合法的 war, 可以被外部的 tomcat 正确加载.

因此, 无论是在开发中直接启动, 还是输出为 jarwar 并当做普通 java 程序来运行, 还是输出为 war 并由外部 tomcat 加载, 都是正常的.