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

相关推荐
皮皮林5514 小时前
Java性能调优黑科技!1行代码实现毫秒级耗时追踪,效率飙升300%!
java
冰_河5 小时前
QPS从300到3100:我靠一行代码让接口性能暴涨10倍,系统性能原地起飞!!
java·后端·性能优化
桦说编程7 小时前
从 ForkJoinPool 的 Compensate 看并发框架的线程补偿思想
java·后端·源码阅读
躺平大鹅9 小时前
Java面向对象入门(类与对象,新手秒懂)
java
初次攀爬者10 小时前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺10 小时前
搞懂@Autowired 与@Resuorce
java·spring boot·后端
Derek_Smart11 小时前
从一次 OOM 事故说起:打造生产级的 JVM 健康检查组件
java·jvm·spring boot
NE_STOP12 小时前
MyBatis-mybatis入门与增删改查
java
孟陬16 小时前
国外技术周刊 #1:Paul Graham 重新分享最受欢迎的文章《创作者的品味》、本周被划线最多 YouTube《如何在 19 分钟内学会 AI》、为何我不
java·前端·后端