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编译原理

相关推荐
重生之我是Java开发战士2 分钟前
【Java SE】反射、枚举与Lambda表达式
java·开发语言
weixin_436525074 分钟前
若依多租户版 - @ApiEncrypt, api接口加密
java·开发语言
Hello.Reader11 分钟前
Flink Java 版本兼容性与 JDK 模块化(Jigsaw)踩坑11 / 17 / 21 怎么选、怎么配、怎么稳
java·大数据·flink
TechPioneer_lp18 分钟前
小红书后端实习一面|1小时高强度技术追问实录
java·后端·面试·个人开发
TH_137 分钟前
37、SQL的Explain
java·数据库·sql
康王有点困43 分钟前
Flink部署模式
java·大数据·flink
EndingCoder43 分钟前
属性和参数装饰器
java·linux·前端·ubuntu·typescript
芒克芒克1 小时前
LeetCode 134. 加油站(O(n)时间+O(1)空间最优解)
java·算法·leetcode·职场和发展
huahailing10241 小时前
Spring 循环依赖终极解决方案:从原理到实战(附避坑指南)
java·后端·spring
jiaguangqingpanda2 小时前
Day28-20260124
java·数据结构·算法