如果在Maven中,这个问题其实很容易解决。只需要在parent标签中写入parent的坐标即可,Maven会自动下载并继承parent的属性。但是在Gradle中,这个问题似乎非常不方便。它是通过parent的include来包含的。但是在子项目单独构建的时候,上层目录是没有父项目的,这种情况下,需要如何解决呢?就像普通的多模块依赖一样,可以继承父模块的subprojects属性。
我的项目结构简化后大概是这样的:
parent │ .gitignore │ .gitmodules │ build.gradle │ gradlew │ gradlew.bat │ HELP.md │ settings.gradle └─server │ .gitignore │ build.gradle │ Dockerfile │ gradlew │ gradlew.bat │ HELP.md │ ├─gradle │ └─wrapper │ gradle-wrapper.jar │ gradle-wrapper.properties │ └─src
在我的parent的build.gradle中,定义了一下子项目的依赖和插件:
subprojects { apply plugin: 'java' ... dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' ... } }
使用gitmodules方式,将parent和server存放在不同的git仓库中:
.gitmodules
[submodule "server"] path = server url = <https://gitee.com/xxxxx> branch = master
现在的问题是,如果在本地运行,没有任何问题,因为它们在同一目录下,可以通过相对路径找到彼此,但是当要使用CI/CD时,相对路径就不在起作用了。例如,如果在server项目的build.gradle中有这个属性:
sourceCompatibility = '17'
这是一个非常简单的属性,用于设置编译版本。如果在本地,通过parent的subproject,在server中编译时不会出错。但是一般情况下,当提交到自己的仓库时,由于无法获取到parent了(因为parent和server都有自己的仓库),就会报错,因为没有插件’java’。这导致了本地构建和CI/CD环境中结果的不一致。如果是在Maven中,server可以通过parent的坐标获取到这个pom文件,然后继承它,所以没有什么影响。但是在Gradle中,应该怎么做呢?
gradle在这方面比maven更灵活,因为你可以有多种模型可供选择,你可以选择互不依赖,也可以选择继承依赖,还可以选择做成一个模块互相调用(官方更推荐第三种)
gradle官方文档都有,而且这几种模型我都用过,早年我用的是第二种模式,就是所有的子模块默认继承父模块的依赖,后来官方不推荐了,改为了声明模块在子模块调用的方式,因为这种模式你可以感知,而第一种方式子模块不可感知,所以官方推荐后一种。我用gradle都5年了,从gradle 1.3版本就开始用了,后来gradle的用法也是改了很多次,包括声明模块的方式调用都是gradle 5.0之后推荐的内容了