在Java后端开发中,几乎每一个项目最终都要面临一个问题:到底打包成JAR还是WAR?
尤其是用Spring Boot的项目,许多人一知半解,要么一股脑全打JAR,要么死守传统WAR,结果踩坑无数。
今天把这两种打包方式的区别、底层原理、适用场景、实际项目选型经验一次性讲透,读完这篇你再也不用纠结。
一、JAR 和 WAR 的本质区别
JAR(Java Archive)
- 本质:就是一个ZIP压缩包,里面放.class文件、资源文件、MANIFEST.MF清单文件
- 最经典的可执行JAR结构(Spring Boot默认就是这种):
- your-app.jar
├── org/springframework/boot/loader/JarLauncher.class ← Spring Boot启动器
├── META-INF/MANIFEST.MF ← Main-Class指向JarLauncher
├── BOOT-INF/classes/ ← 你的代码
├── BOOT-INF/lib/ ← 所有依赖jar(fat jar/uber jar)
└── dependencies/(旧版本) - 关键点:可以把Tomcat/Jetty/Undertow这些Web服务器也打进去(embedded container),真正实现“一个JAR走天下”
WAR(Web Application Archive)
- 本质:同样是ZIP压缩包,但必须遵循J2EE/Servlet规范的目录结构
- 标准结构:
- your-app.war
├── WEB-INF/
│ ├── web.xml(可选,目前Spring Boot可以不要)
│ ├── classes/ ← 你的.class文件
│ ├── lib/ ← 项目依赖的jar
│ └── lib-provided/ ← 容器已提供的(如servlet-api)
├── META-INF/
│ └── MANIFEST.MF
├── index.jsp / static / templates 等静态资源
└── lib/(有时也放外部lib) - 关键点:必须部署到外部Servlet容器(Tomcat、Jetty、WildFly、WebLogic等)才能运行
二、2025年最真实的区别对比表
|
对比维度 |
JAR(Spring Boot可执行JAR) |
WAR(传统/外部容器) |
|
是否包含Web服务器 |
是(嵌入Tomcat/Jetty/Undertow) |
否,必须外部容器 |
|
启动方式 |
java -jar app.jar |
复制到tomcat/webapps,启动Tomcat |
|
部署速度 |
极快(单文件,直接运行) |
较慢(需要启动外部Tomcat) |
|
端口占用 |
自己占8080,可随意改 |
必须跟容器端口一致,或配置虚拟主机 |
|
云原生/K8s友善度 |
极高(Docker镜像最小,启动秒级) |
一般(镜像大,启动慢) |
|
热部署支持 |
开发模式下支持(spring-boot-devtools) |
Tomcat支持,但不如JAR爽 |
|
依赖管理 |
全打进去(fat jar,一般50-100MB) |
容器提供部分依赖(如servlet-api) |
|
打包大小 |
较大(全量依赖) |
较小(依赖可由容器提供) |
|
集群部署冲突 |
几乎无(每个实例独立) |
容易冲突(多个war共用一个Tomcat) |
|
运维复杂度 |
极低(一个文件搞定) |
高(要维护Tomcat集群) |
|
适合微服务 |
完美(目前99%微服务都用JAR) |
基本淘汰 |
三、2025年真实项目该怎么选?
强烈推荐打JAR的场景(99%的新项目都该这么干)
- 所有Spring Boot新项目(2023年后来)
- 默认就是可执行JAR,启动快、部署简单、云原生完美支持国内大厂(阿里、腾讯、字节、美团、京东)2025年新项目几乎100%用JAR
- 微服务架构(Spring Cloud、Dubbo、Go/Micro等)
- 每个服务独立JAR,K8s部署一个Pod一个JAR,扩缩容零负担阿里云、腾讯云、AWS都推荐这种方式
- Docker容器化部署
- FROM eclipse-temurin:21-jre
COPY app.jar /app.jar
CMD [“java”, “-jar”, “/app.jar”] - 镜像只有100MB左右,启动3-5秒
- Serverless/函数计算
- 阿里云函数计算、腾讯云SCF直接支持JAR上传运行
- 内部工具、定时任务、数据处理服务
- 直接java -jar运行,运维小哥哥爱死你
必须或提议打WAR的场景(只剩这些了)
- 公司强制要求部署到已有的大Tomcat/WebLogic/WebSphere集群
- 许多银行、运营商、传统国企还在用共享Tomcat集群这种情况下只能打WAR,否则无法部署
- 需要多个应用共享同一批依赖或配置
- 列如所有项目共用同一个Oracle驱动、同一套安全框架放在Tomcat的shared/lib里,WAR可以不重复打包(节省一点点空间)
- 使用一些老古董框架(Struts2 + JSP + EJB)
- 这些框架本身就要求WAR结构
- 公司有严格的容器管理规范
- 列如所有应用必须部署到统一管理的WebLogic集群做JMX监控、统一安全策略
四、Spring Boot项目如何切换JAR/WAR?
默认就是JAR,不用改
想打WAR,只需三步:
- pom.xml中修改打包方式
- <packaging>war</packaging>
- 继承SpringBootServletInitializer
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 排除嵌入式Tomcat(如果要用外部容器)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope> <!-- 关键! -->
</dependency>
打完就是标准WAR,可以扔到Tomcat/webapps下运行,也能java -jar运行(双模式支持!)
最终结论
- 新项目、微服务、云原生、Docker/K8s → 坚决打JAR,毫不犹豫
- 只有在“必须部署到公司已有外部容器集群”这种极端情况下才打WAR
- 99%的开发者这辈子可能只打一次WAR(就是那次被老项目折磨的时候)
目前是2025年了,还在纠结打WAR的,不是公司有历史包袱,就是自己没跟上时代。
一句话总结:
能打JAR的,绝对不打WAR。
打JAR才是当代Java程序员的体面!

© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
您必须登录才能参与评论!
立即登录
war包是以前前后端未分离的项目打包方式,包含所有class文件,xml,jsp,html文件。
前端工程部署在哪?你说用nginx部署前端,但生产环境上nginx是部署在外网区,由其转发请求访问内网区,安全规定不允许外网区部署任何代码,只能部署内网,这时候前端和后端(打war包)一起部署到tmomcat不是更方便?
没遇到过你这种情况,我一般都是。前后端分离的,前端部署在一台服务器上,后端部署在另外一台服务器上,然后是通过nginx转发。没遇到你说的这种情况。
用war有个好处,拷贝文件小,并且易替换class。