Spring Boot 打包部署,JAR vs WAR

简介: 无论选择JAR还是WAR部署方式,关键在于匹配团队的技术栈、运维能力和业务需求。Spring Boot的灵活性支持两种部署模式,为不同场景提供了合适的解决方案。

大家好,我是小悟。

一、JARWAR 打包的区别

JAR (Java ARchive)

  • 独立运行:内嵌Tomcat/Jetty服务器,可直接通过 java -jar 运行
  • 微服务友好:适合云原生、容器化部署
  • 简化部署:单个可执行文件,无需外部Web服务器
  • 默认方式Spring Boot 默认打包为可执行JAR

WAR (Web Application ARchive)

  • 传统部署:需要外部Servlet容器(如Tomcat、WebLogic)
  • 企业环境:适合需要部署到现有应用服务器的场景
  • 共享资源:多个应用可共享服务器资源
  • 配置分离:服务器配置与应用分离

二、详细打包部署步骤

项目结构

my-springboot-app/
├── src/
│   └── main/
│       ├── java/com/example/
│       └── resources/
└── pom.xml 或 build.gradle

1. 打包为可执行JAR(默认方式)

Maven 配置 (pom.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)

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 = ''
}

主启动类

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);
    }
}

打包命令

# Maven
mvn clean package
# Gradle
./gradlew clean build

运行JAR

# 直接运行
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 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>

修改启动类

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配置

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

# Maven
mvn clean package
# Gradle
./gradlew clean build

部署到外部Tomcat

准备Tomcat服务器

# 下载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文件

# 复制WAR文件到webapps目录
cp target/myapp.war /opt/tomcat/webapps/
# 或者使用管理界面部署
# 访问 http://localhost:8080/manager/html

Tomcat配置优化(conf/server.xml)

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           maxThreads="200"
           minSpareThreads="10"
           enableLookups="false"
           acceptCount="100"
           disableUploadTimeout="true"/>

启动/停止Tomcat

# Linux
./bin/startup.sh
./bin/shutdown.sh
# Windows
bin\startup.bat
bin\shutdown.bat

3. 配置文件管理

application.yml 示例

# 公共配置
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

# 使用多阶段构建
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

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 示例

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)

# /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

部署脚本

#!/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

选择建议:

  1. 选择JAR的情况
  • 微服务架构
  • 容器化部署(Docker/K8s)
  • 云原生应用
  • 需要快速独立部署
  • 无现有应用服务器


  1. 选择WAR的情况
  • 传统企业IT环境
  • 已有Tomcat/WebLogic集群
  • 需要与其他Java EE应用共享资源
  • 运维团队熟悉传统部署模式
  • 需要与旧系统集成


最佳实践:

  1. 对于新项目,优先考虑JAR部署,更符合现代架构
  2. 统一配置管理:无论JAR/WAR,使用外部配置文件
  3. 健康检查:集成Spring Boot Actuator用于监控
  4. 日志集中:使用Logback/SLF4J,日志输出到文件或日志系统
  5. 安全加固:生产环境关闭开发特性,使用HTTPS
  6. 自动化部署:结合CI/CD流水线实现自动化

通过合理的打包部署策略,可以确保Spring Boot应用在不同环境中的稳定运行和高效维护。


Spring Boot 打包部署,JAR vs WAR.png


谢谢你看我的文章,既然看到这里了,如果觉得不错,随手点个赞、转发、在看三连吧,感谢感谢。那我们,下次再见。


您的一键三连,是我更新的最大动力,谢谢

山水有相逢,来日皆可期,谢谢阅读,我们再会

我手中的金箍棒,上能通天,下能探海

相关文章
|
Java 应用服务中间件 微服务
信创迁移适配实战-SpringBoot项目打包war部署至TongWeb7
信创迁移适配实战-SpringBoot项目打包war部署至TongWeb7
5416 0
信创迁移适配实战-SpringBoot项目打包war部署至TongWeb7
|
4月前
|
人工智能 算法 知识图谱
算法对齐还是实战突围?解构GEO优化中方法论与实践的权重博弈
在AIGC重塑信息检索的当下,GEO(生成式引擎优化)已成为品牌流量增长新基座。专家于磊提出“人性化GEO”理念,首创“两大核心+四轮驱动”方法论,融合语义对齐、EEAT原则与结构化知识图谱,兼顾算法可信度与实践适应性,推动AI搜索从技术博弈回归用户价值。(239字)
248 18
|
弹性计算 Java Linux
手把手教你把Springboot项目部署到阿里云教程
手把手教你把Springboot项目部署到阿里云教程成功连接远程云服务器和配置阿里云安全组
2949 1
|
Java 应用服务中间件 Maven
如何将 Spring Boot 应用程序部署为 WAR?
如何将 Spring Boot 应用程序部署为 WAR?
979 1
|
5月前
|
消息中间件 运维 监控
SpringBoot 整合 RabbitMQ:和这只“兔子”交朋友
RabbitMQ 就像是一个超级邮差兔,不过它不送胡萝卜,专门传递消息!交换机(Exchange),队列(Queue),路由键(Routing Key),消息(Message)。
337 10
|
5月前
|
运维 监控 Java
SpringBoot 实现QPS监控:别等系统“咳血”了才想起装“心电图”!
想象一下你的系统就像一个忙碌的外卖小哥,QPS就是他每秒能送多少份外卖!如果小哥每秒只能送1单,那估计顾客早就饿晕在厕所了;要是每秒能送100单,那他绝对是"闪电侠"附体!
281 4
|
4月前
|
监控 负载均衡 Dubbo
SpringBoot整合Dubbo,构建高性能分布式系统
Dubbo是阿里巴巴开源的一款高性能、轻量级的 Java RPC 框架,主要功能包括:面向接口的远程方法调用、智能负载均衡、服务自动注册与发现、高可用性、运行期流量调度、可视化的服务治理。
355 13
|
4月前
|
存储 缓存 负载均衡
SpringBoot整合Zookeeper,实现分布式集群部署
Zookeeper是一个分布式的、开源的分布式应用程序协调服务,是Google的Chubby一个开源的实现。它提供了一组简单的原语,使得分布式应用能够基于这些原语实现更高层次的服务。
552 4
|
4月前
|
监控 NoSQL Java
SpringBoot + Redis分布式锁深度剖析,性能暴涨的秘密全在这里
分布式锁是在分布式系统中协调多个节点对共享资源进行互斥访问的机制。当多个服务实例需要访问共享资源时,分布式锁能确保同一时刻只有一个实例可以执行关键代码段。
291 3