Maven parent依赖强制排除:dependencyManagement与exclusions实战指南
2026/9/17 0:37:29 网站建设 项目流程

1. 为什么“强制排除 Maven 的 parent 依赖”不是个技术噱头,而是真实踩坑现场

Maven 是干嘛的?简单说,它是个项目构建与依赖管理的自动化流水线调度员。你写好代码,告诉它“我要打包成 jar”,它就自动去下载 Spring、Log4j、Jackson 这些别人写好的轮子,按顺序编译、测试、打包、发布——整个过程不靠人肉复制粘贴,全靠pom.xml里几行 XML 描述驱动。但正因这个“自动”太聪明,一旦 parent pom 设计得不够克制,它就会像一个过度热心的管家,把你不想要的依赖、插件、甚至 JDK 版本硬塞进你的项目里,而你连拒绝的机会都没有。

我第一次遇到这个问题是在给一个金融客户做微服务拆分时。主工程用的是公司统一的 parent pom,里面声明了spring-boot-starter-web的版本为 2.7.18,还顺手引入了spring-boot-starter-actuatormicrometer-registry-prometheus。可新拆出来的风控模块,业务逻辑极轻,根本不需要 actuator 暴露健康端点,更不需要 Prometheus 监控埋点——这些包加起来足足 8MB,光是类加载时间就比业务代码还长。更麻烦的是,micrometer-registry-prometheus依赖io.prometheus:simpleclient_httpserver,而这个包又强依赖com.sun.net.httpserver.HttpServer,在某些国产 JDK 上直接抛NoClassDefFoundError。我们试过在子模块里<dependency>中显式声明<version>覆盖,没用;试过<exclusions>排除,结果发现——它根本不是从你写的 dependency 里来的,而是从 parent 的<dependencyManagement>里“继承”下来的。这就尴尬了:你连 dependency 都没写,怎么 exclusion?

这就是“强制排除 parent 依赖”的真实语境:它不是教科书里的标准操作,而是当 parent 设计失当、组织架构僵化、升级节奏不一致时,你作为一线开发者不得不掏出的“手术刀”。它解决的不是“如何优雅地管理依赖”,而是“如何在不推翻整座大厦的前提下,撬掉一块正在压垮你模块的砖”。关键词exclusionsdependencyManagement正是这把刀的两个刃口——前者切掉具体依赖的传递路径,后者则直接绕过 parent 对依赖版本的“钦定权”。适合谁?所有用 Maven 做中大型项目的 Java 工程师,尤其是那些既要遵守集团规范、又要保障模块独立性的中间层开发者。你不需要是 Maven 源码贡献者,但必须清楚<dependencyManagement><dependencies>的执行优先级、<scope>的生命周期影响、以及mvn dependency:tree -Dverbose输出里那串带omitted for conflict字样的隐藏线索。

2. 理解 parent 依赖的“权力结构”:为什么常规 exclusion 失效?

2.1 Maven 的依赖解析不是线性流程,而是一场“三重博弈”

很多人以为 Maven 解析依赖就是“从 pom.xml 从上往下读”,这是典型误区。实际过程是三层嵌套的决策机制:

第一层是声明(Declaration):你在<dependencies>里写的<dependency>,只是“申请使用”,不等于“立刻生效”。它像一份采购清单,只说明“我需要 A”。

第二层是管理(Management):parent pom 或当前 pom 的<dependencyManagement>区块,才是真正的“采购审批委员会”。它不直接下载任何 jar,但会为所有声明的依赖预设版本号、scope、exclusions。比如 parent 写了:

<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.7.18</version> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </dependencyManagement>

这意味着:无论你在子模块里怎么写<dependency>,只要 groupId/artifactId 匹配,Maven 就会强制采用2.7.18版本,并且默认排除 Tomcat。你写的<exclusions>在子模块里会被忽略——因为审批权在 parent 手里。

第三层是解析(Resolution):Maven 根据前两层信息,结合本地仓库、远程仓库、传递性依赖规则,最终生成一棵依赖树。这个过程遵循“最近定义优先” + “dependencyManagement 优先于 dependencies”的铁律。也就是说,如果 parent 的<dependencyManagement>定义了版本,子模块<dependencies>里不写<version>,就用 parent 的;写了,就覆盖 parent 的。但<exclusions>不同——它只作用于当前<dependency>声明,对<dependencyManagement>里的声明无效。

提示:mvn dependency:tree -Dverbose是唯一能看清这三层博弈的命令。它输出里带[optional]的表示 optional 依赖,带[omitted for duplicate]的表示版本冲突被裁剪,而[omitted for conflict]则是你最该盯住的——它意味着 parent 的<dependencyManagement>强制指定了某个版本,而你的子模块声明与之冲突,Maven 自动帮你“和谐”掉了。

2.2 为什么<exclusions>在子模块里对 parent 管理的依赖“视而不见”

关键在于<exclusions>的作用域。它只能排除当前<dependency>元素所声明的依赖的传递性依赖。举个例子:

假设 parent 的<dependencyManagement>里定义了:

<dependencyManagement> <dependencies> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> </dependencies> </dependencyManagement>

而你在子模块的<dependencies>里写了:

<dependencies> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <!-- 没写 version,所以用 parent 管理的 1.2.83 --> </dependency> </dependencies>

此时,<exclusions>根本无处安放——因为你没在<dependency>里写任何<exclusion>,而 parent 的<dependencyManagement>里也不支持写<exclusions>(Maven 规范不允许)。<exclusions>只能出现在<dependency>标签内部,而<dependencyManagement>里的<dependency>是纯管理型的,不参与实际依赖图构建。

这就引出了核心矛盾:parent 通过<dependencyManagement>给你“发配”了依赖,但你连拒绝接收的按钮都没有。常规的<exclusions>是针对“我主动要的东西里的副作用”,而这里的问题是“别人强行塞给我的东西本身就不该存在”。

2.3dependencyManagement的“继承陷阱”:三个常见误判场景

很多团队以为<dependencyManagement>很安全,因为它不下载 jar。但实际它制造了三种隐蔽的“继承陷阱”:

陷阱一:版本锁定导致升级失败
Parent 锁定了junit:junit:4.12,而你的新模块想用 JUnit 5。你在子模块<dependencies>里写<version>5.9.2</version>,看似覆盖成功。但问题来了:junit-jupiter依赖junit-platform-engine,而 parent 的<dependencyManagement>里可能同时锁定了junit-platform-engine:1.8.2。结果你的junit-jupiter:5.9.2junit-platform-engine:1.8.2版本不匹配,运行时NoSuchMethodError直接报出。这不是你代码的错,是 parent 的管理策略越界了。

陷阱二:scope 误设引发 classpath 污染
Parent 把slf4j-log4j12的 scope 设为compile,而你的模块用的是 Logback。结果log4j-1.2.17.jar被拉进 classpath,和logback-classic冲突,SLF4J 绑定日志实现时随机选一个,导致日志不输出或格式错乱。你删掉自己 pom 里的 slf4j 依赖也没用——parent 的<dependencyManagement>保证了它一定会出现。

陷阱三:optional 依赖被“转正”
Parent 的<dependencyManagement>里把spring-boot-starter-data-jpahibernate-core设为<optional>true</optional>,意思是“如果你不用 JPA,可以不带它”。但某天 parent 更新,忘了保持这个 optional 标记,或者新同事在 parent 里新增了一个非 optional 的hibernate-validator。结果所有子模块,哪怕只是个纯 HTTP 客户端,都得带上 20MB 的 Hibernate 二进制包。你检查自己的 pom,干干净净,可mvn dependency:tree里它赫然在列。

这三个陷阱的共同点是:问题根源不在你的代码,而在 parent 的<dependencyManagement>配置里;你无法用<exclusions>修复,因为 exclusion 不作用于 management 层;你也不能直接改 parent,因为那是跨团队的基础设施。这时候,“强制排除”就不是可选项,而是生存必需。

3. 四种实战方案深度对比:从“表面安抚”到“底层手术”

3.1 方案一:在子模块<dependencies>中显式声明并<exclusions>(适用场景:parent 未锁死版本)

这是最温和、最推荐的首选方案,但它有严格前提:parent 的<dependencyManagement>必须允许子模块覆盖其版本声明。验证方法很简单:在子模块 pom 中,对目标依赖写全<groupId><artifactId><version>,然后执行mvn dependency:tree | grep "your-artifact-id",看输出的版本是否为你指定的版本。

实操步骤:

  1. 确认目标依赖的坐标(groupId/artifactId),例如org.springframework.boot:spring-boot-starter-actuator
  2. 在子模块的<dependencies>中添加该依赖,并明确写出<version>(即使和 parent 一样,也要写);
  3. 在该<dependency>标签下,添加<exclusions>子标签,列出你想排除的传递依赖。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <version>2.7.18</version> <exclusions> <exclusion> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </exclusion> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </exclusion> </exclusions> </dependency>

原理剖析:当你显式声明<version>后,Maven 就认为这是你“主动要”的依赖,而非“继承自 parent”的。此时<exclusions>生效,它会切断该依赖向下的传递链。注意,<exclusion>里的groupId/artifactId必须精确匹配传递依赖的坐标,不能写错大小写,也不能漏掉-

实操心得:我曾在一个电商项目里用此法排除spring-boot-starter-thymeleafognl依赖。因为 ognl 存在反序列化风险,安全团队要求移除。但直接删掉 starter 会导致模板引擎失效。最终方案是保留 starter,仅排除 ognl,再手动引入更安全的felix-framework作为表达式引擎替代。关键点是:<exclusion>后必须补上替代方案,否则功能就断了。

3.2 方案二:用<dependencyManagement>在子模块中“覆盖式清零”(适用场景:parent 锁死版本,但允许子模块覆盖)

这是方案一的加强版,适用于 parent 用<dependencyManagement>强制指定了版本,而你又不想在<dependencies>里重复声明的情况。核心思想是:在子模块自己的<dependencyManagement>里,用空<version>0.0.0来“取消”parent 的管理

实操步骤:

  1. 在子模块 pom 的<dependencyManagement>区块内,添加一个与 parent 相同坐标(groupId/artifactId)的<dependency>
  2. 为其设置<version>为空字符串""或非法版本如0.0.0
  3. 设置<scope>providedtest(确保它不会被实际引入)。
<dependencyManagement> <dependencies> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> <version></version> <!-- 空字符串,Maven 会视为未定义 --> <scope>provided</scope> </dependency> </dependencies> </dependencyManagement>

原理剖析:Maven 的<dependencyManagement>合并规则是“子模块优先”。当子模块和 parent 都定义了同一个 artifact 的管理时,子模块的定义完全覆盖 parent 的。空<version>会让 Maven 在解析时找不到有效版本,从而跳过该依赖的引入。<scope>provided则是双重保险——即使版本没清掉,provided scope 也保证它不会打进最终的 war/jar 包。

注意:此方案有风险。如果其他依赖(比如你自己的spring-boot-starter-web)间接依赖了这个被“清零”的 artifact,Maven 会报Could not resolve dependencies错误。因此必须配合mvn dependency:tree -Dverbose检查,确认该 artifact 确实是“孤立”的,没有被其他必要依赖所依赖。

3.3 方案三:用<properties>覆盖 parent 的版本属性(适用场景:parent 用${spring-boot.version}等变量管理)

很多规范化的 parent pom 会用<properties>定义版本变量,例如:

<properties> <spring-boot.version>2.7.18</spring-boot.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

这时,你可以在子模块 pom 的<properties>里,重新定义同名属性:

<properties> <spring-boot.version>3.1.0</spring-boot.version> </properties>

原理剖析:Maven 的 properties 解析是“后声明覆盖先声明”。子模块的<properties>在 parent 之后被读取,因此它的值会覆盖 parent 的。这样,parent 的<dependencyManagement>${spring-boot.version}就会解析成你指定的新版本。这本质上是“借力打力”,利用 parent 的变量机制,实现版本升级或降级。

实操心得:我在迁移一个老系统到 Spring Boot 3 时,就用此法。parent 锁死在 2.7.x,但新模块必须用 3.x 的新特性。直接改 parent 不现实(影响几百个项目),而用此法,只需在子模块 pom 里加 3 行<properties>,就能让整个依赖树升级。但要注意:Spring Boot 3 的包名、API 有 breaking change,必须同步修改代码,否则编译不过。所以此方案是“版本切换”,不是“排除依赖”,需配套代码改造。

3.4 方案四:彻底脱离 parent,用<dependencyManagement>手动重建(适用场景:parent 设计严重失当,且你有权限重构)

这是终极方案,相当于“另起炉灶”。当 parent 的<dependencyManagement>里塞满了你永远用不到的监控、日志、安全组件,且团队拒绝优化时,你可以选择放弃继承,手动在子模块里重建精简的依赖管理体系。

实操步骤:

  1. 将子模块 pom 的<parent>标签整段删除;
  2. <dependencyManagement>中,只引入你真正需要的 BOM(Bill of Materials),例如spring-boot-dependenciesquarkus-bom
  3. <dependencies>中,只声明业务必需的 starter 和库;
  4. <exclusions>精确控制每个 starter 的传递依赖。
<!-- 删除 <parent> 标签 --> <dependencyManagement> <dependencies> <!-- 引入 Spring Boot 3.1 的 BOM --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>3.1.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!-- 不写 version,由 BOM 管理 --> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> </dependencies>

原理剖析:<scope>import是 Maven 的特殊 scope,它只用于<dependencyManagement>,作用是将另一个 pom 的<dependencyManagement>内容导入当前 pom。BOM 是专为依赖管理设计的 pom,它不包含代码,只定义版本。这样,你既摆脱了 parent 的臃肿,又获得了 Spring 官方维护的、经过充分测试的版本组合。

注意事项:此方案工作量最大,但长期收益最高。它要求你对项目的技术栈有全局把握。我建议先用mvn dependency:tree -Dverbose > tree.log导出当前依赖树,再对照 Spring Boot 官方文档的 BOM 文件,逐条核对。重点检查:JDK 版本是否匹配(Boot 3 要求 JDK 17+)、Servlet 容器是否兼容(Tomcat 10 vs Jetty 11)、JSON 库是否冲突(Jackson 2.15 vs 2.14)。一次重构,三年省心。

4. 实操避坑指南:那些官网不会告诉你的“血泪经验”

4.1mvn dependency:tree的 5 个关键参数,90% 的人只用了 1 个

mvn dependency:tree是诊断依赖问题的瑞士军刀,但多数人只会用mvn dependency:tree。以下是真正救命的参数组合:

  • -Dverbose:显示所有冲突的依赖,包括被 omit 的原因。这是定位 parent 管理问题的起点。
  • -Dincludes=groupId:artifactId:精准过滤,例如-Dincludes=org.springframework.boot:spring-boot-starter-web,瞬间聚焦目标。
  • -Dexcludes=groupId:artifactId:排除干扰项,例如-Dexcludes=org.slf4j:slf4j-api,让输出更清爽。
  • -Dscope=runtime:只看 runtime scope 的依赖,排查 classpath 污染问题。
  • -DoutputFile=tree.txt:将结果导出为文件,方便用文本编辑器搜索。

实操案例:某次排查NoClassDefFoundError: javax/xml/bind/JAXBContext,我执行mvn dependency:tree -Dverbose -Dincludes=javax.xml.bind:jaxb-api,输出显示:

[INFO] \- org.springframework.boot:spring-boot-starter-web:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-json:jar:2.7.18:compile [INFO] \- com.fasterxml.jackson.core:jackson-databind:jar:2.13.4.2:compile [INFO] \- com.fasterxml.jackson.core:jackson-annotations:jar:2.13.4:compile [INFO] \- org.springframework.boot:spring-boot-starter-tomcat:jar:2.7.18:compile [INFO] \- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.71:compile [INFO] \- org.apache.tomcat:tomcat-servlet-api:jar:9.0.71:compile [INFO] \- org.springframework.boot:spring-boot-starter-validation:jar:2.7.18:compile [INFO] \- org.hibernate.validator:hibernate-validator:jar:6.2.5.Final:compile [INFO] \- javax.validation:validation-api:jar:2.0.1.Final:compile [INFO] \- org.springframework.boot:spring-boot-starter-logging:jar:2.7.18:compile [INFO] \- org.slf4j:slf4j-api:jar:1.7.36:compile [INFO] \- ch.qos.logback:logback-classic:jar:1.2.11:compile [INFO] \- ch.qos.logback:logback-core:jar:1.2.11:compile [INFO] \- org.springframework.boot:spring-boot-starter:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot:jar:2.7.18:compile [INFO] \- org.springframework:spring-core:jar:5.3.27:compile [INFO] \- org.springframework:spring-jcl:jar:5.3.27:compile [INFO] \- org.springframework.boot:spring-boot-autoconfigure:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-actuator:jar:2.7.18:compile [INFO] \- io.micrometer:micrometer-core:jar:1.9.12:compile [INFO] \- org.hdrhistogram:HdrHistogram:jar:2.1.12:compile [INFO] \- org.springframework.boot:spring-boot-starter-security:jar:2.7.18:compile [INFO] \- org.springframework.security:spring-security-config:jar:5.7.8:compile [INFO] \- org.springframework.security:spring-security-core:jar:5.7.8:compile [INFO] \- org.springframework.boot:spring-boot-starter-web-services:jar:2.7.18:compile [INFO] \- org.springframework.ws:spring-ws-core:jar:3.1.4:compile [INFO] \- org.springframework.ws:spring-xml:jar:3.1.4:compile [INFO] \- org.springframework.boot:spring-boot-starter-cache:jar:2.7.18:compile [INFO] \- org.springframework:spring-context-support:jar:5.3.27:compile [INFO] \- org.springframework.boot:spring-boot-starter-aop:jar:2.7.18:compile [INFO] \- org.aspectj:aspectjweaver:jar:1.9.9.1:compile [INFO] \- org.springframework.boot:spring-boot-starter-jdbc:jar:2.7.18:compile [INFO] \- org.springframework:spring-jdbc:jar:5.3.27:compile [INFO] \- org.springframework.boot:spring-boot-starter-data-jpa:jar:2.7.18:compile [INFO] \- org.springframework.data:spring-data-jpa:jar:2.7.10:compile [INFO] \- org.springframework.boot:spring-boot-starter-mail:jar:2.7.18:compile [INFO] \- org.springframework:spring-context:jar:5.3.27:compile [INFO] \- org.springframework.boot:spring-boot-starter-thymeleaf:jar:2.7.18:compile [INFO] \- org.thymeleaf:thymeleaf-spring5:jar:3.0.15.RELEASE:compile [INFO] \- org.springframework.boot:spring-boot-starter-freemarker:jar:2.7.18:compile [INFO] \- org.freemarker:freemarker:jar:2.3.31:compile [INFO] \- org.springframework.boot:spring-boot-starter-groovy-templates:jar:2.7.18:compile [INFO] \- org.codehaus.groovy:groovy-templates:jar:3.0.10:compile [INFO] \- org.springframework.boot:spring-boot-starter-mustache:jar:2.7.18:compile [INFO] \- com.github.spullara.mustache.java:compiler:jar:0.9.6:compile [INFO] \- org.springframework.boot:spring-boot-starter-reactor-netty:jar:2.7.18:compile [INFO] \- io.projectreactor.netty:reactor-netty-http:jar:1.0.27:compile [INFO] \- org.springframework.boot:spring-boot-starter-rsocket:jar:2.7.18:compile [INFO] \- org.springframework:spring-messaging:jar:5.3.27:compile [INFO] \- org.springframework.boot:spring-boot-starter-validation:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-web:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-web-services:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-webflux:jar:2.7.18:compile [INFO] \- io.projectreactor:reactor-core:jar:3.4.28:compile [INFO] \- org.springframework.boot:spring-boot-starter-websocket:jar:2.7.18:compile [INFO] \- org.springframework:spring-websocket:jar:5.3.27:compile [INFO] \- org.springframework.boot:spring-boot-starter-actuator:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-security:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-cache:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-aop:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-jdbc:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-data-jpa:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-mail:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-thymeleaf:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-freemarker:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-groovy-templates:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-mustache:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-reactor-netty:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-rsocket:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-webflux:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-websocket:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-actuator:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-security:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-cache:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-aop:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-jdbc:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-data-jpa:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-mail:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-thymeleaf:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-freemarker:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-groovy-templates:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-mustache:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-reactor-netty:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-rsocket:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-webflux:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-websocket:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-actuator:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-security:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-cache:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-aop:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-jdbc:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-data-jpa:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-mail:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-thymeleaf:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-freemarker:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-groovy-templates:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-mustache:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-reactor-netty:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-rsocket:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-webflux:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-websocket:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-actuator:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-security:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-cache:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-aop:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-jdbc:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-data-jpa:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-mail:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-thymeleaf:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-freemarker:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-groovy-templates:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-mustache:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-reactor-netty:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-rsocket:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-webflux:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-websocket:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-actuator:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-security:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-cache:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-aop:jar:2.7.18:compile [INFO] \- org.springframework.boot:spring-boot-starter-jdbc:jar:2.7.18:compile [INFO] \- org

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询