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

推荐订阅源

A
Arctic Wolf
博客园 - 聂微东
F
Fortinet All Blogs
云风的 BLOG
云风的 BLOG
小众软件
小众软件
V
Visual Studio Blog
博客园 - 三生石上(FineUI控件)
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Apple Machine Learning Research
Apple Machine Learning Research
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Cloudflare Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
The GitHub Blog
The GitHub Blog
Y
Y Combinator Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园_首页
L
LangChain Blog
A
About on SuperTechFans
阮一峰的网络日志
阮一峰的网络日志
I
Intezer
T
The Blog of Author Tim Ferriss
Security Latest
Security Latest
C
CXSECURITY Database RSS Feed - CXSecurity.com
Know Your Adversary
Know Your Adversary
Simon Willison's Weblog
Simon Willison's Weblog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
P
Palo Alto Networks Blog
Scott Helme
Scott Helme
S
Secure Thoughts
Spread Privacy
Spread Privacy
T
Threat Research - Cisco Blogs
Attack and Defense Labs
Attack and Defense Labs
P
Privacy & Cybersecurity Law Blog
O
OpenAI News
H
Heimdal Security Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Help Net Security
Help Net Security
C
Cyber Attacks, Cyber Crime and Cyber Security
Blog — PlanetScale
Blog — PlanetScale
GbyAI
GbyAI
G
Google Developers Blog
博客园 - Franky
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
K
Kaspersky official blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
T
Tor Project blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Tenable Blog
Google Online Security Blog
Google Online Security Blog
PCI Perspectives
PCI Perspectives

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 加载, 都是正常的.