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

相关推荐
像我这样帅的人丶你还15 小时前
Java 后端详解(四):分页与搜索
java·javascript·后端
她的男孩15 小时前
数据权限为什么不能只靠注解?Forge 的 Mapper 层 SQL 改写源码拆解
java·后端·架构
tntxia16 小时前
Mybatis的日志输入
java
亦暖筑序18 小时前
Java 8老系统Browser Agent实战:三层拦截把AI操作后台变成可审计流程
java·后端·设计模式
用户2986985301421 小时前
Java 实现 Word 文档加密与权限解除
java·后端
Yeats_Liao21 小时前
14:Servlet中的页面跳转-Java Web
java·后端·架构
未秃头的程序猿21 小时前
告别"if-else地狱"!Java 21模式匹配,代码优雅了10倍
java·后端·面试
鹤望兰6751 天前
字节跳动国际支付-后端开发-三面面经
java
Flittly1 天前
【AgentScope Java新手村系列】(14)人机交互
java·spring boot·spring
RainCity1 天前
Java Swing 自定义组件库分享(十二)
java·笔记·后端