maven scope引起的程序崩溃

最近新开了一个从0开始的项目,之前项目运行正常,升级springboot到3.x后,项目启动不报错,但是突然崩溃,查看控制台:

复制代码
[ionShutdownHook] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext

发现是pom.xml突然多了一个依赖,最后取出scope后服务启动正常。** 关键是写完这篇博客后,发现有scope=provided服务也能正常启动了,TMD **

复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>

scope作用域

我们把程序的整个周期分为编译、测试、运行三个阶段,这三个阶段对应到mvn的compile test packagemaven scope作用域有compile provided test runtime system import六个阶段。

下面通过一个案例演示scope的作用过程:

同一个项目中存在servicecommon两个模块,并且service引用common,service#pom如下,整个mvn命令都在service根目录下执行

复制代码
<dependency>
    <groupId>com.bottle</groupId>
    <artifactId>common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

compile域

引用jar打包阶段:

  • 编译
  • 测试
  • 运行
场景1

环境:

复制代码
<dependency>
    <groupId>com.bottle</groupId>
    <artifactId>common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <scope>compile</scope>
</dependency>

因为compile是贯穿整个周期,所以整个过程不存在引用问题。

  • mvn clean compile 正常
  • mvn clean test 正常
  • mvn clean package 正常
  • java -jar target/service-0.0.1-SNAPSHOT.war 正常

provided域

引用jar打包阶段:

  • 编译
  • 测试
  • 运行
场景1 (编译war)

环境:

复制代码
<dependency>
    <groupId>com.bottle</groupId>
    <artifactId>common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <scope>provided</scope>
</dependency>

测试结果:

  • mvn clean compile

  • mvn clean test

  • mvn clean package

  • java -jar target/service-0.0.1-SNAPSHOT.war
    测试结果竟然全部通过,跟前面的理论上对不上,这就有点很那啥了,查看包结构:

    jar tf target/service-0.0.1-SNAPSHOT.war


providedscope竟然也罢依赖包打包了,这一点后续还需要继续研究。

场景2 (编译jar)

一切也都正常!!!所以网上很多说provided不会打包的没有复现,也不确定是哪里出了问题???

test域

引用jar打包阶段:

  • 编译
  • 测试
  • 运行
场景1(业务代码引用包是必须的情况):
复制代码
<dependency>
    <groupId>com.bottle</groupId>
    <artifactId>common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <scope>test</scope>
</dependency>

测试结果:

  • mvn clean compile 编译失败

  • mvn clean test 编译失败

  • mvn clean package 编译失败

  • java -jar target/service-0.0.1-SNAPSHOT.war 不会生成war包
    因为test域引用jar只存在test阶段,所以compile阶段编译失败,自然后续整个阶段都会失败。compile、test和package都会报这个错误,而这个就是编译阶段的错误:

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.14.0:compile (default-compile) on project service: Compilation failure: Compilation failure:

以上是业务包强依赖的情况,如果只使用test包做一些单元测试,就是另一种场景

场景2(引入测试包):
复制代码
<dependency>
    <groupId>com.bottle</groupId>
    <artifactId>common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <version>5.8.2</version>
    <scope>test</scope>
</dependency>

单元测试类代码:

复制代码
@Slf4j
@SpringBootTest
class ServiceApplicationTests {

    @BeforeAll
    public static void init() {
        log.warn("======================== step:test =============================");
    }

    @Test
    void contextLoads() {
    }
}

因为test域引用jar只存在test阶段,所以compile阶段编译失败,自然后续整个阶段都会失败

  • mvn clean compile 正常
  • mvn clean test 正常,同时包括了单元测试内容

    可以看到test阶段做了很多事情,也打印了单元测试的日志
  • mvn clean package 打包正常
  • java -jar target/service-0.0.1-SNAPSHOT.war 运行正常

runtime域

引用jar打包阶段:

  • 编译
  • 测试
  • 运行

编译阶段不需要,测试、运行阶段需要的就是tomcat、servlet相关的一些包,所以只模拟tomcat场景

场景1:
复制代码
<packaging>war</packaging>

<dependency>
    <groupId>com.bottle</groupId>
    <artifactId>common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>runtime</scope>
</dependency>

测试结果:

  • mvn clean compile

  • mvn clean test

  • mvn clean package 打包失败
    很奇怪的现象,前面都正常,打包报错:

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-war-plugin:3.4.0:war (default-war) on project service: Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/web.xml if executing in update mode) -> [Help 1]

  • java -jar target/service-0.0.1-SNAPSHOT.war 不会生成war包

重新调整,去除tomcat作用域scope

场景2:
复制代码
<packaging>war</packaging>

<dependency>
    <groupId>com.bottle</groupId>
    <artifactId>common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

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

测试结果:

  • mvn clean compile

  • mvn clean test

  • mvn clean package

  • java -jar target/service-0.0.1-SNAPSHOT.war
    观察war包结构:

    jar tf target/service-0.0.1-SNAPSHOT.war


既然war包打包失败,尝试使用jar包重新打包

场景3:
复制代码
<packaging>jar</packaging>

<dependency>
    <groupId>com.bottle</groupId>
    <artifactId>common</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

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

测试结果:

  • mvn clean compile

  • mvn clean test

  • mvn clean package

  • java -jar target/service-0.0.1-SNAPSHOT.jar
    无runtime的war和jar包都能正常打包和运行,这一点就是打包规则的问题了,观察jar包结构:

    jar tf target/service-0.0.1-SNAPSHOT.jar

tomcat依赖打包正常

但是我发现lombok的结构竟然被修改了,本来lombok的scope=provided,正常打包后也存在WEB-INF/lib-provided的包结构也被破坏

** 垃圾maven!!! 明天继续 **

mvn编译原理

相关推荐
cyforkk几秒前
Java 并发编程教科书级范例:深入解析 computeIfAbsent 与方法引用
java·开发语言
后青春期的诗go3 分钟前
泛微OA-E9与第三方系统集成开发企业级实战记录(八)
java·接口·金蝶·泛微·oa·集成开发·对接
dreamxian7 分钟前
苍穹外卖day09
java·spring boot·tomcat·log4j·maven
剑海风云8 分钟前
JDK 26之安全增强
java·开发语言·安全·jdk26
左左右右左右摇晃10 分钟前
Java并发——多线程
java·开发语言·jvm
23.13 分钟前
【Java】字符串底层与常量池演变全解析
java·开发语言·jvm
极客先躯18 分钟前
高级java每日一道面试题-2025年9月09日-数据处理篇[LangChain4j]-金融行业使用 LLM 有哪些合规要求?
java·金融·高级面试题·权限与访问控制·数据脱敏与隐私计算·模型可解释性工具·审计日志与监控
jing-ya33 分钟前
day 59 图论part10
java·开发语言·数据结构·算法·图论
短剑重铸之日1 小时前
《ShardingSphere解读》16 改写引擎:如何理解装饰器模式下的 SQL 改写实现机制?
java·数据库·后端·sql·shardingsphere·分库分表·装饰器模式
q5431470871 小时前
VScode 开发 Springboot 程序
java·spring boot·后端