1. 简介

在本教程中,我们将探讨通过 mvn spring-boot:run 命令运行 Spring Boot Web 应用程序与通过 java -jar 命令运行打包后的 jar/war 文件之间的区别。

我们假设你已经了解 Spring Boot 的 repackage 目标配置。如需深入了解,请参考《使用 Spring Boot 创建可部署 Fat Jar 应用》。

2. Spring Boot Maven 插件

在编写 Spring Boot 应用时,推荐使用 Spring Boot Maven 插件 来构建、测试和打包代码。

该插件提供了许多便捷功能,例如:

  • 自动解析正确的依赖版本
  • 可以将所有依赖(包括嵌入式应用服务器)打包进一个可执行的 fat jar/war
  • 自动管理 classpath,无需手动指定 -cp 参数
  • 实现自定义的 ClassLoader,用于加载嵌套在包内的依赖 jar 文件
  • 自动查找 main() 方法并写入 MANIFEST.MF,无需手动指定主类

3. 使用 Maven 以解压形式运行代码

在开发 Web 应用时,可以利用 Spring Boot Maven 插件的另一个功能:自动将应用部署到嵌入式服务器中。

只需要添加如下依赖即可启用 Tomcat:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId> 
</dependency>

然后在项目根目录执行:

$ mvn spring-boot:run

插件会根据配置自动下载 Tomcat 并启动服务器,日志如下:

[INFO] --- spring-boot-maven-plugin:2.1.3.RELEASE:run (default-cli) @ spring-boot-ops ---
...
11:33:36.648 [main] INFO  o.a.catalina.core.StandardService - Starting service [Tomcat]
11:33:36.649 [main] INFO  o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.16]
...
11:33:48.223 [main] INFO  o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8080"]
11:33:48.289 [main] INFO  o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path ''
11:33:48.292 [main] INFO  org.baeldung.boot.Application - Started Application in 22.454 seconds (JVM running for 37.692)

当看到 Started Application 时,说明服务已经启动完毕,可以通过 http://localhost:8080 访问。

4. 以独立打包应用形式运行代码

开发完成后,进入部署阶段,我们需要将应用打包成可执行文件。

⚠️ 注意:使用普通 mvn package 生成的 jar 不包含依赖,只能作为库使用。

4.1. 插件配置

通常只需添加 Spring Boot Maven 插件:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

如果你的项目有多个 main() 方法,需指定入口类:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <configuration>
                <mainClass>com.baeldung.webjar.WebjarsdemoApplication</mainClass>
            </configuration>
        </execution>
    </executions>
</plugin>

或使用 start-class 属性:

<properties>
    <start-class>com.baeldung.webjar.WebjarsdemoApplication</start-class>
</properties>

4.2. 执行打包并运行

运行以下命令打包并启动:

$ mvn clean package spring-boot:repackage
$ java -jar target/spring-boot-ops.war

如需了解如何运行 jar 文件,请参考《使用命令行参数运行 Jar 应用》。

4.3. war 文件结构

解压 spring-boot-ops.war 后可以看到:

  • META-INF/MANIFEST.MF:自动生成的清单文件
  • WEB-INF/classes/:编译后的类文件
  • WEB-INF/lib/:依赖 jar 文件
  • WEB-INF/lib-provided/:运行嵌入式服务器所需的依赖
  • org/springframework/boot/loader/:Spring Boot 自定义类加载器

4.4. war 文件的 MANIFEST.MF

内容包含:

Start-Class: com.baeldung.webjar.WebjarsdemoApplication
Main-Class: org.springframework.boot.loader.WarLauncher

其中 Main-Class 指定了启动类加载器。

4.5. jar 文件结构

将打包方式改为 jar 后重新打包,结构如下:

  • BOOT-INF/classes/:编译后的类文件
  • BOOT-INF/lib/:外部依赖库

4.6. jar 文件的 MANIFEST.MF

内容包含:

Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Version: 2.1.3.RELEASE
Main-Class: org.springframework.boot.loader.JarLauncher

这些配置告诉类加载器去哪里加载类和依赖。

5. 如何选择

选择运行方式时,要根据所处阶段来判断:开发阶段还是生产环境。

5.1. 开发阶段

✅ 优势:

  • 无需手动配置环境变量、启动服务器等
  • 一行命令即可启动完整服务
  • 支持多模块、多配置文件管理(通过 Maven profiles)

✅ 适合本地快速开发调试。

5.2. 生产阶段

❌ 不建议使用 mvn spring-boot:run,原因如下:

  • 需要安装 Maven 和 JDK
  • 代码需上传服务器,存在泄露风险
  • 每次启动都要重新编译,浪费资源(CPU、内存、费用)
  • 多实例部署时重复操作繁琐

✅ 推荐使用打包后的 jar/war 文件部署,便于统一管理、快速部署、减少依赖。

6. 总结

本教程对比了两种常见的 Spring Boot 应用启动方式:

方式 适用阶段 优点 缺点
mvn spring-boot:run 开发阶段 快速启动、无需打包 需安装 Maven、代码暴露
java -jar 生产部署 独立运行、安全、便于部署 需打包构建,部署前需测试

选择合适的方式,有助于提升开发效率和部署稳定性。

源码地址:GitHub


原始标题:Running a Spring Boot App with Maven vs an Executable Jar

» 下一篇: Java Weekly, 第293期