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

相关推荐
未若君雅裁35 分钟前
MyBatis 一级缓存、二级缓存与清理机制
java·缓存·mybatis
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题 第65题】【JVM篇】第25题:谈谈对 OOM 的认识
java·开发语言·jvm
阿维的博客日记2 小时前
Nacos 为什么能让配置动态生效?(涉及 @RefreshScope 注解)
java·spring
雨辰AI2 小时前
SpringBoot3 + 人大金仓读写分离 + 分库分表 + 集群高可用 全栈实战
java·数据库·mysql·政务
辰海Coding3 小时前
MiniSpring框架学习-完成的 IoC 容器
java·spring boot·学习·架构
小小编程路3 小时前
C++ 多线程与并发
java·jvm·c++
AI视觉网奇3 小时前
linux 检索库 判断库是否支持
java·linux·服务器
她的男孩4 小时前
从零搭一个企业后台,为什么我把能力拆成 Starter 和 Plugin
java·后端·架构
RainCity4 小时前
Java Swing 自定义组件库分享(七)
java·笔记·后端
Sam_Deep_Thinking4 小时前
连锁门店的外卖订单平台对接
java·微服务·架构·系统架构