在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上传运行
- 内部工具、定时任务、数据处理服务
必须或建议打WAR的场景(只剩这些了)- 公司强制要求部署到已有的大Tomcat/WebLogic/WebSphere集群
- 很多银行、运营商、传统国企还在用共享Tomcat集群这种情况下只能打WAR,否则无法部署
- 需要多个应用共享同一批依赖或配置
- 比如所有项目共用同一个Oracle驱动、同一套安全框架放在Tomcat的shared/lib里,WAR可以不重复打包(节省一点点空间)
- 使用一些老古董框架(Struts2 + JSP + EJB)
- 公司有严格的容器管理规范
- 比如所有应用必须部署到统一管理的WebLogic集群做JMX监控、统一安全策略
四、Spring Boot项目如何切换JAR/WAR?默认就是JAR,不用改想打WAR,只需三步:- pom.xml中修改打包方式
- <packaging>war</packaging>
- 继承SpringBootServletInitializer
@SpringBootApplicationpublic class Application extends SpringBootServletInitializer {@Overrideprotected 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程序员的体面! 查看详情:https://www.toutiao.com/article/7580596583172784682 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |