Java 项目打包与部署完全指南:JAR vs WAR,从构建到运行

Java 项目打包与部署完全指南:JAR vs WAR,从构建到运行

1. 引言

项目开发完成后,如何将其部署到服务器上,让用户能够访问?对于 Java 开发者而言,打包部署 是上线前最后、也是最关键的一步。Java 项目通常打包成两种格式:JARWAR。选择哪种包,以及如何部署,取决于项目类型、运行环境和团队习惯。

本文将从零开始,带你全面了解:

  • ✅ JAR 包与 WAR 包的本质区别和适用场景
  • ✅ 使用 Maven/Gradle 打包的具体命令
  • ✅ 部署 JAR 包的多种方式(前台、后台、参数配置)
  • ✅ 部署 WAR 包到 Tomcat 的详细步骤
  • ✅ 部署流程全景图与常见问题排查

无论你是刚入门的开发者,还是需要负责上线任务的工程师,都能从中获得实用的指导。


2. JAR vs WAR:核心区别

WAR包
传统 Web 项目

需要外置容器
不含 Web 容器
需部署到 Tomcat/Jetty 等
JAR包
普通 Java 项目

或 Spring Boot
包含内嵌 Web 容器

Tomcat/Jetty/Undertow
直接 java -jar 运行

维度 JAR 包 WAR 包
全称 Java ARchive Web Application ARchive
包含内容 类文件、依赖库、配置文件(可能含内嵌容器) 类文件、依赖库、配置文件、Web 资源(JSP/HTML)
运行方式 java -jar xxx.jar(独立进程) 放置在外部 Web 容器的 webapps 目录下,启动容器
适用场景 Spring Boot / Spring Cloud 微服务、命令行工具 传统单体 Web 应用、需要部署在统一管理的 Tomcat 集群
容器依赖 无需安装额外容器 必须预先安装 Tomcat/Jetty/JBoss 等
启动速度 快(直接启动) 相对慢(需启动容器)
资源占用 每个 JAR 独立占用内存 多个 WAR 可共享同一个容器进程

3. 打包前的准备:项目类型判断

在打包之前,先明确你的项目是什么类型:

  • 如果是 Spring Boot 项目(默认打包为 JAR,但也可配置为 WAR)
  • 如果是 传统 Servlet/JSP 项目(通常打包为 WAR)
  • 如果是 纯工具类/批处理应用(一定是 JAR)

可以通过 pom.xml(Maven)或 build.gradle(Gradle)中的打包配置判断。

Maven 示例

xml 复制代码
<!-- 打包为 JAR -->
<packaging>jar</packaging>

<!-- 打包为 WAR -->
<packaging>war</packaging>

Gradle 示例

groovy 复制代码
// 打包为 JAR
apply plugin: 'java'

// 打包为 WAR
apply plugin: 'war'

4. 打包命令详解

4.1 Maven 项目

命令 作用
mvn clean 删除 target 目录,清理旧文件
mvn compile 编译源代码
mvn test 运行测试用例
mvn package 打包(生成 JAR/WAR 到 target 目录)
mvn install 打包并安装到本地 Maven 仓库
mvn deploy 打包并部署到远程仓库(如 Nexus)

常用组合

bash 复制代码
# 跳过测试,快速打包
mvn clean package -DskipTests

# 生成可执行 JAR(需 Spring Boot Maven 插件)
mvn clean package spring-boot:repackage

4.2 Gradle 项目

命令 作用
gradle clean 删除 build 目录
gradle build 编译、测试、打包
gradle build -x test 跳过测试打包

打包后的文件位置:

  • Maven:target/xxx.jartarget/xxx.war
  • Gradle:build/libs/xxx.jarbuild/libs/xxx.war

5. 部署 JAR 包

5.1 基本运行命令

bash 复制代码
java -jar app.jar

该命令会在前台 运行,按 Ctrl + C 会终止进程,关闭终端也会导致进程退出。

5.2 后台运行(Linux/Unix)

bash 复制代码
nohup java -jar app.jar > app.log 2>&1 &
  • nohup:忽略挂断信号,关闭终端后进程继续运行
  • > app.log:标准输出重定向到文件
  • 2>&1:将错误输出也重定向到同一个文件
  • &:后台运行

查看进程:ps -ef | grep app.jar

停止进程:kill -9 <PID>

5.3 指定参数

5.3.1 系统属性(-D)
bash 复制代码
java -Dserver.port=8081 -Dspring.profiles.active=prod -jar app.jar
5.3.2 命令行参数(--)

Spring Boot 支持使用 -- 直接覆盖配置:

bash 复制代码
java -jar app.jar --server.port=8081 --spring.datasource.url=jdbc:mysql://localhost:3306/mydb
5.3.3 外部配置文件
bash 复制代码
java -jar app.jar --spring.config.location=/path/to/application.yml

5.4 常见 JVM 调优参数

bash 复制代码
java -Xms512m -Xmx2g -XX:+UseG1GC -jar app.jar
  • -Xms:初始堆内存
  • -Xmx:最大堆内存
  • -XX:+UseG1GC:使用 G1 垃圾回收器

5.5 使用 systemd 管理 JAR(生产推荐)

创建服务文件 /etc/systemd/system/myapp.service

ini 复制代码
[Unit]
Description=My Spring Boot Application
After=network.target

[Service]
User=appuser
ExecStart=/usr/bin/java -jar /opt/myapp/app.jar
SuccessExitStatus=143
Restart=always

[Install]
WantedBy=multi-user.target

启用并启动:

bash 复制代码
systemctl daemon-reload
systemctl enable myapp
systemctl start myapp
systemctl status myapp

6. 部署 WAR 包

6.1 部署到 Tomcat

步骤 1:安装 Tomcat
bash 复制代码
# 下载并解压
wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.89/bin/apache-tomcat-9.0.89.tar.gz
tar -xzf apache-tomcat-9.0.89.tar.gz
cd apache-tomcat-9.0.89
步骤 2:放置 WAR 包

将生成的 .war 文件复制到 Tomcat 的 webapps 目录下:

bash 复制代码
cp myapp.war /path/to/tomcat/webapps/

Tomcat 会自动解压并部署(默认会监听 8080 端口)。访问地址:http://localhost:8080/myapp/

步骤 3:启动 Tomcat
bash 复制代码
./bin/startup.sh   # Linux
# 或
./bin/startup.bat  # Windows
步骤 4:查看日志
bash 复制代码
tail -f logs/catalina.out
步骤 5:停止 Tomcat
bash 复制代码
./bin/shutdown.sh

6.2 部署优化

  • 配置虚拟路径 :修改 conf/server.xml,添加 <Context> 元素。

  • 热部署 :将 WAR 放到 webapps 后,Tomcat 会自动重新部署(但生产环境不建议)。

  • 内存配置 :修改 bin/catalina.sh(或 setenv.sh):

    bash 复制代码
    export JAVA_OPTS="-Xms512m -Xmx2g"

6.3 其他容器

  • Jetty :将 WAR 放到 webapps 目录,运行 java -jar start.jar
  • WebLogic / WebSphere:通过管理控制台部署

7. 部署流程全景图

Spring Boot

微服务/工具类
传统 Web 项目
前台
后台
服务化
开发完成
项目类型
打包为 JAR
打包为 WAR
上传到服务器
运行方式
java -jar app.jar
nohup java -jar app.jar &
配置 systemd / supervisor
验证应用接口
安装 Tomcat/Jetty
将 WAR 放入 webapps
启动容器
通过浏览器访问


8. 常用命令速查表

操作 命令
Maven 打包(跳过测试) mvn clean package -DskipTests
Gradle 打包 gradle clean build
运行 JAR(前台) java -jar app.jar
运行 JAR(后台) nohup java -jar app.jar > /dev/null 2>&1 &
指定端口运行 JAR java -jar app.jar --server.port=8081
查看 JAR 进程 `ps -ef
停止 JAR 进程 kill -9 <PID>
启动 Tomcat ./bin/startup.sh
停止 Tomcat ./bin/shutdown.sh
查看 Tomcat 日志 tail -f logs/catalina.out
查看端口占用 `netstat -tlnp

9. 常见问题与解决方案

9.1 JAR 包运行提示 "no main manifest attribute"

原因 :打包时没有指定主类(Main-Class)。
解决 (Spring Boot):确保 spring-boot-maven-plugin 已配置。

xml 复制代码
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

9.2 WAR 包部署后访问 404

  • 检查 webapps 下是否生成了同名目录。
  • 确认访问路径:http://ip:port/项目名/
  • 查看 logs/catalina.out 是否有部署错误。

9.3 端口冲突

bash 复制代码
# 查看端口占用
netstat -anp | grep 8080
# 修改运行端口
java -jar app.jar --server.port=8081

9.4 内存溢出(OOM)

增加堆内存限制:

bash 复制代码
java -Xms1g -Xmx2g -jar app.jar

9.5 后台运行的 JAR 如何查看实时日志?

bash 复制代码
tail -f app.log   # 如果重定向到了文件
# 或使用 journalctl(systemd 管理时)
journalctl -u myapp -f

10. 总结与最佳实践

场景 推荐方式
微服务、云原生应用 JAR + systemd(或 Docker)
传统单体 Web 应用,与运维统一管理 WAR + Tomcat
开发调试 java -jar 前台运行
生产环境 systemd / supervisor 管理 JAR,或使用容器编排
需要动态调整参数 使用 --spring.config.location 外部化配置

部署检查清单

  • ✅ 打包前运行所有测试
  • ✅ 使用 -DskipTests 加速构建(仅当测试已覆盖)
  • ✅ 配置 JVM 堆大小和垃圾回收器
  • ✅ 将配置文件外置,避免重新打包
  • ✅ 配置日志轮转(如 logrotate)
  • ✅ 设置健康检查端点,配合监控系统

下期预告:Docker 化部署 Spring Boot 应用:从 Dockerfile 到 Kubernetes

相关推荐
云烟成雨TD6 小时前
Spring AI Alibaba 1.x 系列【62】时光旅行(Time-Travel)
java·人工智能·spring
浩少7026 小时前
【无标题】
java·开发语言
一棵白菜6 小时前
java 学习
java
卷毛的技术笔记6 小时前
Java后端硬核实战:用Spring AI Alibaba+Redis给LLM装上“超强记忆中枢”
java·人工智能·redis·后端·spring·ai·系统架构
AKA__Zas8 小时前
初识多线程(3.0)
java·开发语言·学习方法
北漂人Java8 小时前
SpringAI-2.Spring AI整合本地模型和云端大模型
java·spring
迹象Kimizhou_blog8 小时前
国内 IntelliJ IDEA 集成Claude code,调用deepSeek模型实现agent
java·ide·intellij-idea·deepseek·claude code
百珏8 小时前
海量人群包存储优化:基于 RoaringBitmap 交换格式与 Redis 分片 Bitmap 的实践
java·后端·架构
风味蘑菇干8 小时前
IO流(字节流)
java