前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >记录解决 Spring Boot 项目继承依赖导致编译失败问题

记录解决 Spring Boot 项目继承依赖导致编译失败问题

作者头像
哎_小羊
发布2019-05-25 19:48:45
2.7K0
发布2019-05-25 19:48:45
举报
文章被收录于专栏:哎_小羊哎_小羊

问题背景,公司一个使用 Spring Boot 的 Mutil 项目,根据 Spring Boot 官方文档配置好 Parent 继承 spring-boot-starter-parent POM 的时候可以正常编译运行,但是正式上线时,需要切换到继承公司统一的插件集合 Parent POM (这里暂称为:common-plugin,该插件是为了方便执行一些持续集成编译自动化插件,例如 maven-deploy-pluginmaven-docker-plugin 等等插件),然后问题就出现了,编译不通过,类似提示找不到类,找不到符号的错误消息。

我们都知道,根据 Spring Boot 官网文档 中指出,项目需要配置继承 spring-boot-starter-parent 作为父 POM 如下:

代码语言:javascript
复制
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.2.RELEASE</version>
</parent>

.....

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

类似这样子配置,此时执行编译 mvn clean package 是没有问题哒!但是,目前的情况是,我们的项目需要继承自己的 Parent POM(common-plugin),此时在执行编译,这种方式就行不通啦!因为一个 POM 文件中只能继承一个 Parent。当然肯定有人会说,我们可以把 spring-boot-starter-parent 依赖配置到 common-plugin 里面就可以啦! 首先这种方式是没有问题的,但是考虑到 common-plugin 作为一个公用 POM 自定义插件集合,配置后被公司所有项目组继承使用,且不说会不会出现各种 jar 版本依赖问题, 就 Spring 相关的 jar 版本依赖问题,就比较难处理啦!不能顾此失彼,这种方式成本太高,风险较大。那么该怎么办呢?其实 Spring Boot 官网文档 中给出了解决方案,项目父 POM 配置如下:

代码语言:javascript
复制
<dependencyManagement>
    <dependencies>
        <dependency>
            <!-- Import dependency management from Spring Boot -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.0.2.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

上边的配置,同样可以起到继承 Parent POM 方式相同的作用,同时解决了多 Parent 不支持的问题。这里要提一点的是,对于 Muti 项目各个子模块中不需要再次配置依赖 spring-boot-dependencies,只需要继承父项目 POM 即可(这里因为父 POM 已经继承了该依赖,子模块继承传递)。如果在子模块中再次添加了该依赖如下,那么编译会报错。

代码语言:javascript
复制
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
</dependency>

所以,子模块不需要再次添加该依赖。还要指出的是,父项目继承了 spring-boot-dependencies 依赖后,子模块继承父项目 POM,那么子模块使用到相关依赖的时候,不需要指定 version 版本了。例如子模块配置如下:

代码语言:javascript
复制
<dependencies>
    ......
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

不需要指定依赖 version,这是因为在 spring-boot-dependencies POM 中已经定义好了对应的版本,我们可以从 Maven 仓库 pom 文件可以看到这些依赖的版本定义如下:

代码语言:javascript
复制
<dependencies>
    ......
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>2.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
        <version>2.0.2.RELEASE</version>
    </dependency>
</dependencies>

好了,到这里基本就能解决由于 Parent POM 依赖导致的编译失败问题,不过,事情并没有结束。在修改完以上配置后,再次编译依旧卡在一个子项目的某个文件上,提示找不到类,找不到符号,错误信息类似如下:

代码语言:javascript
复制
.....
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile (default-compile) on project bop-service-crm: Compilation failure: Compilation failure:
[ERROR] /Users/wanyang3/git/mutiproject/sub_project_service/src/main/java/com/test/service/modul/impl/ModuleServiceImpl.java:[21,47] 找不到符号
[ERROR] 符号:   类 RestController
[ERROR] 位置: 程序包 org.springframework.web.bind.annotation
[ERROR] /Users/wanyang3/git/mutiproject/sub_project_service/src/main/java/com/test/service/modul/impl/ModuleServiceImpl.java:[47,2] 找不到符号
[ERROR] 符号: 类 RestController
......

What? 从 IDE 中可以看到这个 org.springframework.web.bind.annotation.RestController 是有的呀!尝试注释一下父 POM 中 Parent POM common-plugin 代码依赖,发现执行编译可以通过,说明问题还是出在 common-plugin 中。

仔细观察下,org.springframework.web.bind.annotation.RestController 这个类属于 spring-web 包里面的,然后分别查询一下这两个 Parent POM 中 spring 相关的版本,惊奇的发现,他们都定义了各自的 spring 版本。common-plugin 中定义了 <spring.version>3.0.6.RELEASE</spring.version>,而 spring-boot-dependencies Parent POM 中定义了 <spring.version>4.3.14.RELEASE</spring.version>,而只使用后者时,编译是可以通过的,只使用前者时,编译不通过。那么接下来,我们统一一下 Spring 版本为 4.3.14.RELEASE,看下是否可以编译通过。

我们采用覆盖 common-plugin 中的 spring.version 方式来完成版本统一,首先放开上边注释的代码,然后在项目父 POM 中配置 spring.version 属性。

代码语言:javascript
复制
<parent>
    <artifactId>common-plugin</artifactId>
    <groupId>com.plugin.common</groupId>
    <version>1.1.0</version>
</parent>
......    
<properties>
    ......
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
    <spring.version>4.3.14.RELEASE</spring.version>
</properties>

这样就可以指定项目使用 4.3.14.RELEASE 版本啦!再次执行编译,发现编译通过啦!!!看来还是版本依赖冲突的问题啊!

参考资料

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年06月04日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
持续集成
CODING 持续集成(CODING Continuous Integration,CODING-CI)全面兼容 Jenkins 的持续集成服务,支持 Java、Python、NodeJS 等所有主流语言,并且支持 Docker 镜像的构建。图形化编排,高配集群多 Job 并行构建全面提速您的构建任务。支持主流的 Git 代码仓库,包括 CODING 代码托管、GitHub、GitLab 等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档