大家好,我是小悟。
一、JAR 和 WAR 打包的区别
JAR (Java ARchive)
- 独立运行 :内嵌Tomcat/Jetty服务器,可直接通过
java -jar运行 - 微服务友好:适合云原生、容器化部署
- 简化部署:单个可执行文件,无需外部Web服务器
- 默认方式:Spring Boot 默认打包为可执行JAR
WAR (Web Application ARchive)
- 传统部署:需要外部Servlet容器(如Tomcat、WebLogic)
- 企业环境:适合需要部署到现有应用服务器的场景
- 共享资源:多个应用可共享服务器资源
- 配置分离:服务器配置与应用分离
二、详细打包部署步骤
项目结构
css
my-springboot-app/
├── src/
│ └── main/
│ ├── java/com/example/
│ └── resources/
└── pom.xml 或 build.gradle
1. 打包为可执行JAR(默认方式)
Maven 配置 (pom.xml)
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-springboot-app</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging> <!-- 打包为JAR -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Spring Boot Maven 插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.example.MyApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Gradle 配置 (build.gradle)
ini
plugins {
id 'org.springframework.boot' version '3.1.5'
id 'io.spring.dependency-management' version '1.1.3'
id 'java'
}
group = 'com.example'
version = '1.0.0'
sourceCompatibility = '17'
jar {
enabled = true
archiveClassifier = '' // 移除plain后缀
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
}
// 可执行JAR配置
bootJar {
mainClass = 'com.example.MyApplication'
archiveClassifier = ''
}
主启动类
typescript
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
打包命令
bash
# Maven
mvn clean package
# Gradle
./gradlew clean build
运行JAR
ini
# 直接运行
java -jar target/my-springboot-app-1.0.0.jar
# 指定配置文件
java -jar target/my-springboot-app-1.0.0.jar \
--spring.config.location=classpath:/,file:./config/
# 指定端口
java -jar target/my-springboot-app-1.0.0.jar \
--server.port=8081
# 生产环境运行(内存优化)
java -Xms512m -Xmx1024m -jar target/my-springboot-app-1.0.0.jar \
--spring.profiles.active=prod
2. 打包为WAR(用于外部容器)
修改Maven配置
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-springboot-app</artifactId>
<version>1.0.0</version>
<packaging>war</packaging> <!-- 修改为WAR -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 排除内嵌Tomcat -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 添加Servlet API依赖(provided scope) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope> <!-- 由外部容器提供 -->
</dependency>
</dependencies>
<build>
<finalName>myapp</finalName> <!-- WAR文件名称 -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
修改启动类
scala
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(MyApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Gradle WAR配置
bash
plugins {
id 'org.springframework.boot' version '3.1.5'
id 'io.spring.dependency-management' version '1.1.3'
id 'java'
id 'war' // 添加war插件
}
group = 'com.example'
version = '1.0.0'
sourceCompatibility = '17'
configurations {
providedRuntime // 用于provided范围的依赖
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
}
war {
archiveFileName = 'myapp.war'
}
打包WAR
bash
# Maven
mvn clean package
# Gradle
./gradlew clean build
部署到外部Tomcat
准备Tomcat服务器
bash
# 下载Tomcat
wget https://downloads.apache.org/tomcat/tomcat-10/v10.1.13/bin/apache-tomcat-10.1.13.tar.gz
tar -xzf apache-tomcat-10.1.13.tar.gz
cd apache-tomcat-10.1.13
部署WAR文件
bash
# 复制WAR文件到webapps目录
cp target/myapp.war /opt/tomcat/webapps/
# 或者使用管理界面部署
# 访问 http://localhost:8080/manager/html
Tomcat配置优化(conf/server.xml)
ini
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="200"
minSpareThreads="10"
enableLookups="false"
acceptCount="100"
disableUploadTimeout="true"/>
启动/停止Tomcat
python
# Linux
./bin/startup.sh
./bin/shutdown.sh
# Windows
bin\startup.bat
bin\shutdown.bat
3. 配置文件管理
application.yml 示例
yaml
# 公共配置
spring:
application:
name: my-springboot-app
# 开发环境
---
spring:
config:
activate:
on-profile: dev
server:
port: 8080
logging:
level:
root: DEBUG
# 生产环境
---
spring:
config:
activate:
on-profile: prod
server:
port: 8080
compression:
enabled: true
mime-types: text/html,text/xml,text/plain,application/json
logging:
file:
name: /var/log/myapp.log
level:
root: INFO
4. 容器化部署(Docker)
Dockerfile for JAR
bash
# 使用多阶段构建
FROM eclipse-temurin:17-jdk-alpine as builder
WORKDIR /app
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
RUN ./mvnw dependency:go-offline
COPY src ./src
RUN ./mvnw clean package -DskipTests
# 运行阶段
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Dockerfile for WAR + Tomcat
bash
FROM tomcat:10.1-jdk17-temurin
# 移除默认应用
RUN rm -rf /usr/local/tomcat/webapps/*
# 复制WAR文件
COPY target/myapp.war /usr/local/tomcat/webapps/ROOT.war
# 暴露端口
EXPOSE 8080
# 启动Tomcat
CMD ["catalina.sh", "run"]
Docker Compose 示例
yaml
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- DB_HOST=mysql
depends_on:
- mysql
networks:
- app-network
mysql:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=rootpass
- MYSQL_DATABASE=mydb
volumes:
- mysql-data:/var/lib/mysql
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
mysql-data:
三、部署脚本示例
Linux 服务脚本(systemd)
ini
# /etc/systemd/system/myapp.service
[Unit]
Description=My Spring Boot Application
After=network.target
[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/java -Xms512m -Xmx1024m -jar myapp.jar
SuccessExitStatus=143
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
部署脚本
bash
#!/bin/bash
# deploy.sh
APP_NAME="my-springboot-app"
JAR_PATH="target/$APP_NAME-1.0.0.jar"
DEPLOY_DIR="/opt/$APP_NAME"
BACKUP_DIR="$DEPLOY_DIR/backup"
LOG_DIR="/var/log/$APP_NAME"
# 创建目录
mkdir -p $DEPLOY_DIR $BACKUP_DIR $LOG_DIR
# 备份旧版本
if [ -f "$DEPLOY_DIR/$APP_NAME.jar" ]; then
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
mv "$DEPLOY_DIR/$APP_NAME.jar" "$BACKUP_DIR/$APP_NAME-$TIMESTAMP.jar"
fi
# 复制新版本
cp $JAR_PATH "$DEPLOY_DIR/$APP_NAME.jar"
# 设置权限
chmod 755 "$DEPLOY_DIR/$APP_NAME.jar"
# 重启服务
systemctl restart $APP_NAME
# 检查状态
sleep 10
systemctl status $APP_NAME
四、总结对比
| 特性 | JAR 部署 | WAR 部署 |
|---|---|---|
| 部署方式 | 独立运行,内嵌容器 | 依赖外部Servlet容器 |
| 启动命令 | java -jar app.jar |
容器启动(如Tomcat) |
| 适合场景 | 微服务、云原生、容器化 | 传统企业环境、共享服务器 |
| 依赖管理 | 包含所有依赖(fat jar) | 部分依赖由容器提供 |
| 资源占用 | 每个应用独立容器 | 多个应用共享容器资源 |
| 热部署 | 需要重启整个应用 | Tomcat支持部分热部署 |
| 配置管理 | 应用自身管理 | 可与容器配置结合 |
| 监控 | Spring Boot Actuator | 容器管理界面 + Actuator |
选择建议:
- 选择JAR的情况 :
- 微服务架构
- 容器化部署(Docker/K8s)
- 云原生应用
- 需要快速独立部署
- 无现有应用服务器
- 选择WAR的情况 :
- 传统企业IT环境
- 已有Tomcat/WebLogic集群
- 需要与其他Java EE应用共享资源
- 运维团队熟悉传统部署模式
- 需要与旧系统集成
最佳实践:
- 对于新项目,优先考虑JAR部署,更符合现代架构
- 统一配置管理:无论JAR/WAR,使用外部配置文件
- 健康检查:集成Spring Boot Actuator用于监控
- 日志集中:使用Logback/SLF4J,日志输出到文件或日志系统
- 安全加固:生产环境关闭开发特性,使用HTTPS
- 自动化部署:结合CI/CD流水线实现自动化
通过合理的打包部署策略,可以确保Spring Boot应用在不同环境中的稳定运行和高效维护。

谢谢你看我的文章,既然看到这里了,如果觉得不错,随手点个赞、转发、在看三连吧,感谢感谢。那我们,下次再见。
您的一键三连,是我更新的最大动力,谢谢
山水有相逢,来日皆可期,谢谢阅读,我们再会
我手中的金箍棒,上能通天,下能探海