Gradle 仓库及插件依赖代理镜像加速设置,跳过测试
前言
Gradle 作为最常用的项目构建工具之一,Android 和 Java 相关的开发者在日常的工作中肯定是经常打交道的。由于无形的墙或本地复杂的网络环境,会导致依赖编译工具依赖插件或库文件下载缓慢或直接无法下载,项目无法编译打包。这时我们就可以通过设置下载镜像来解决这些问题,我们可以选择配置成公司或自己搭建的 Maven 服务,或者是使用公有云服务商的 Maven 镜像服务,比如阿里云或腾讯云等。这里是以使用阿里云为例,自建和其他的也是类似的设置方式,只是仓库的地址不同。
如何判断依赖插件或库文件无法下载
通常情况下,文件下载不了 Gradle 会直接报错显示到控制台窗口,这种情况就很容易看出问题;但是,有时候 Gradle 并没有报错,一切都看似正常的执行,只是处理 进度一直不动 或卡在某个 Task 里,这时可能就是某些文件下不来导致的。如何查看呢?在项目根目录下执行 Gradle 的脚本任务时加上 --debug 就可以看到 Gradle 编译时执行步骤的详细信息,这里面就可以看到相关的下载信息,可能输出信息会有点多。
# Windows 环境下执行
./gradlew.bat --debug
# *unix/Mac 环境下执行
./gradlew --debug
# 或
bash ./gradlew --debug
构建插件镜像加速
- 全局配置
如果你没有设置 GRADLE_HOME 环境变量的话,默认情况下在用户目录下的 .gradle/ 文件夹下创建文件 init.gradle (这个文件默认是没有创建的,需手动创建),添加以下配置信息即可
settingsEvaluated { settings ->
println "aliyun pluginManagement"
settings.pluginManagement {
repositories {
maven { url "https://maven.aliyun.com/repository/gradle-plugin" }
maven { url "https://maven.aliyun.com/repository/spring-plugin" }
gradlePluginPortal()
}
}
}
- 项目级配置
在项目的根目录下 <project>/settings.gradle 文件中第一行加入,注意这配置必须要放在开头
pluginManagement {
println "aliyun pluginManagement"
repositories {
maven { url "https://maven.aliyun.com/repository/gradle-plugin" }
maven { url "https://maven.aliyun.com/repository/spring-plugin" }
gradlePluginPortal()
}
}
常规依赖库镜像加速
- 全局配置 用户根目录下/
.gradle/init.gradle
buildscript {
repositories {
println "aliyun repositories"
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/public' }
}
allprojects {
println "aliyun allprojects ${project.name}"
repositories {
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/public' }
}
}
}
- 项目级配置 项目根路径/
build.gradle这里以 Spring Boot 为例,Android 项目也是类似
buildscript {
ext {
springBootVersion = '2.0.6.RELEASE'
}
repositories {
maven { url "https://maven.aliyun.com/repository/gradle-plugin" }
maven { url "https://maven.aliyun.com/repository/spring-plugin" }
gradlePluginPortal()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.jacknic'
version = '1.0.0'
sourceCompatibility = 1.8
repositories {
println "aliyun repositories ${project.name}"
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/public' }
}
dependencies {
testImplementation('org.springframework.boot:spring-boot-starter-test')
implementation('org.springframework.boot:spring-boot-starter-web')
}
验证设置是否生效
在项目根路径下执行 .\gradlew.bat 就可以看到以下输入,可以看到我们在配置代码块的闭包中写的 println "aliyun xxxx" 字样的信息在控制台中打印出来,或者查看详细的信息还可以使用 --debug 参数,这样可以看到相关依赖文件的下载链接地址,这样就可以判断文件是否是从镜像站下载的
PS D:\dev\company\project> .\gradlew.bat
aliyun repositories
aliyun pluginManagement
aliyun allprojects app
aliyun allprojects module1
aliyun allprojects module2
aliyun allprojects module3
> Configure project :...
......
完整配置
- 全局配置 在用户根目录下 /
.gradle/init.gradle或者是你已配置的$GRADLE_HOME/init.gradle
// gradle全局配置
settingsEvaluated { settings ->
println "aliyun pluginManagement"
settings.pluginManagement {
repositories {
maven { url "https://maven.aliyun.com/repository/gradle-plugin" }
maven { url "https://maven.aliyun.com/repository/spring-plugin" }
gradlePluginPortal()
}
}
}
buildscript {
repositories {
println "aliyun repositories"
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/public' }
}
allprojects {
println "aliyun allprojects ${project.name}"
repositories {
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/public' }
}
}
}
- 项目单独配置
插件镜像加速项目根目录/settings.gradle,需放在开头
pluginManagement {
repositories {
maven { url "https://maven.aliyun.com/repository/gradle-plugin" }
maven { url "https://maven.aliyun.com/repository/spring-plugin" }
gradlePluginPortal()
}
}
rootProject.name = 'player'
注意点
- 全局配置和项目级配置的区别
- 全局配置是对所有有 Gradle 项目都生效的,但项目级的部分配置可能会覆盖全局的配置
- 项目级配置只对本项目生效,如部分项目需要配置 Maven 的私服可单独配置,并跟随git记录和提交
- Gradle 版本兼容问题
- 如果采取了全局配置的方式,可能会有部分版本兼容问题,旧版本的 Gradle 可能不存在部分配置闭包无法识别问题,这是可以将
init.gradle文件命名为其他名字即可,后续需要再重命名回来。
参考资料
-
Using Gradle Plugins docs.gradle.org/current/use…
-
阿里云仓库服务-指南-gradle 配置指南 developer.aliyun.com/mvn/guide
init.gradle.kts
@file:Suppress("UnstableApiUsage")
import org.gradle.util.GradleVersion
val urlMappingsTencent = mapOf(
"https://repo.maven.apache.org/maven2" to "https://mirrors.tencent.com/nexus/repository/maven-public/",
"https://dl.google.com/dl/android/maven2" to "https://mirrors.tencent.com/nexus/repository/maven-public/",
"https://plugins.gradle.org/m2" to "https://mirrors.tencent.com/nexus/repository/gradle-plugins/"
)
val urlMappingsAliyun = mapOf(
"https://repo.maven.apache.org/maven2" to "https://maven.aliyun.com/repository/central/",
"https://dl.google.com/dl/android/maven2" to "https://maven.aliyun.com/repository/google/",
// "https://plugins.gradle.org/m2" to "https://maven.aliyun.com/repository/gradle-plugin/",
"https://plugins.gradle.org/m2" to "https://mirrors.tencent.com/nexus/repository/gradle-plugins/"
)
/**
* 启用镜像地址映射
*/
fun RepositoryHandler.enableMirror() {
all {
if (this is MavenArtifactRepository) {
val originalUrl = this.url.toString().removeSuffix("/")
urlMappingsTencent[originalUrl]?.let {
logger.lifecycle("Repository $name [$url] is mirrored to $it")
setUrl(it)
}
}
}
}
gradle.allprojects {
buildscript {
repositories.enableMirror()
}
repositories.enableMirror()
}
gradle.beforeSettings {
pluginManagement.repositories.enableMirror()
// 6.8 及更高版本执行 DependencyResolutionManagement 配置
val versionR68 = GradleVersion.version("6.8")
if (GradleVersion.current() >= versionR68) {
val getDrm = settings.javaClass.getDeclaredMethod("getDependencyResolutionManagement")
val drm = getDrm.invoke(settings)
val getRepos = drm.javaClass.getDeclaredMethod("getRepositories")
val repos = getRepos.invoke(drm) as RepositoryHandler
repos.enableMirror()
println("Gradle ${gradle.gradleVersion} DependencyResolutionManagement Configured $settings")
} else {
println("Gradle ${gradle.gradleVersion} DependencyResolutionManagement Ignored $settings")
}
}
Gradle 奇淫技巧之initscript pluginManagement-腾讯云开发者社区-腾讯云
背景
我们的工程结构是单仓,然后通过gradle提供的复合构建(ComposeBuilding) 的机制来完成整个单仓模式的。
单仓就是指所有的代码都在一个仓库内编译,能保证这部分代码的稳定性,尤其是编译产物其实并不是特别可以值得信任的
之前也简单的介绍过复合构建(composebuilding),这个东西虽然好,但是天然具有一个问题,主工程的一部分通用的属性无法复用在符合构建的工程内。
协程 路由 组件化 1+1+1>3 文章是这个 有兴趣的可以看看
那么有没有一种手段可以让类似ext内的属性可以共享到所有复合构建的project上呢?
奇怪的知识
接下来一个个知识点慢慢分析,然后让大家知道都干了些啥。
initscript
这个是gradle 藏的比较深的方法,正常情况下会放在.gradle目录下。官方demo如下。
init.gradle
initscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.apache.commons:commons-math:2.0'
}
}
在gradle的生命周期中,这个是所有的最早执行的方法,我们可以定义一下全局属性都放在这个文件内,之后放在.gradle目录下。
从另外一个方面想哦,在settings.gradle执行之前就能执行initscript了,那么那么我们是不是可以做一些坏事了啊。
简单的说就是这个东西能作用与全局的gradle项目,自然也包括了复合构建的工程。
Plugin
我们一般来写gradle插件会是Plugin<Project>,含义是我们的插件只对于project生效,简单的说就是只要含有build.gradle就可以放入这个插件。
另外一只就是settings插件:Plugin<Settings>,这个一般都是针对于大的工程结构生效的,一个大Project只含有一个settings.gradle,我们可以在这个下面插入我们的plugin。
这次我们介绍的是Plugin<Gradle>,这个是针对Gradle的。你可能不理解了,这个是什么啊。
class RepoSettingsPlugin : Plugin<Settings> {
override fun apply(settings: Settings) {
settings.gradle.addProjectEvaluationListener(object : ProjectEvaluationListener {
})
}
}
其中这个settings.gradle就是我们所说的针对Gradle的了。包括Project实例内也是有Gradle实例的。
Gradle的api虽然不是特别多,但是他可以获取到settings还有project的前置执行,也就是说我们可以提早插入我们想要的东西了。
PluginManagement
原来我们在声明一个插件的时候一定需要在根build.gralde下的buildscripts通过dependencies下,添加classpath来导入插件。

PluginManagement这个是gradle一直推广的新特性了,在AS的大黄蜂版本中已经最为默认配置更新了,我们后续只需要像上图一样,在根节点通过pluginName+version的形式,就可以从PluginManagement获取到对应的插件了。
当然前提是我们需要在settings下添加一些通用的配置。
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
google()
maven {
url "https://dl.bintray.com/kotlin/kotlin-eap"
}
}
}
基本上就和我们使用mavenCentral一样的能力,但是后续我们的一些别的插件就都可以不需要在classpath中声明,只需要在plugins下通过pluginName+version的形式就可以获取到了。
PluginManagement而这个的使用也是有前置条件的。其实这个是一个新的类似pom文件的东西。所以我们的插件在发布的时候需要通过java-gradle-plugin之后定义好gradlePlugin的dsl,这样在mavenPublish的时候就会把对应的文件上传上去了。
gradlePlugin {
plugins {
settingsPlugin {
// 在 app 模块需要通过 id 引用这个插件
id = 'kronos.settings'
// 实现这个插件的类的路径
implementationClass = 'com.kronos.plugin.repo.RepoSettingsPlugin'
}
}
}
当然也有一些极端情况,比如一些插件已经好几个版本没有迭代了,本身也不支持这个特性的情况下,我们其实还是有另外一种方式的。
通过pluginManagement内的resolutionStrategy,之后通过name映射到具体的下载地址的方式,强行使用新的特性。
resolutionStrategy {
eachPlugin {
if (requested.id.id == 'xxxxx') {
useModule('xxx:xxx:version')
}
if (requested.id.id == 'xxxxxx') {
useModule("xxx:xxx:version")
}
}
}
如果在仓库内找不到,的情况下会根据寻找插件的id去指定的地址下载指定版本的plugin。
串起来
我们现在需要的就是在一个工程下,将所有的Project工程都补充上pluginManagement,保证他们的settings还是和原来一样。
这样我们就可以给全局的所有的工程的settings都补充上一样的逻辑,然后我们的切入点只有根节点的settings.gralde的一个插件。
第一个SettingsPlugin看看我是咋写的呢。
class PluginsVersionPlugin : Plugin<Settings> {
override fun apply(target: Settings) {
// 获取到最外面的转化文件
FileUtils.getRootProjectDir(target.gradle)?.let {
IncludeBuildInsertScript().execute(target, it)
}
target.gradle.plugins.apply(PluginVersionGradlePlugin::class.java)
}
}
class IncludeBuildInsertScript {
fun execute(target: Settings, root: File) {
val initFile = getBuildTemp(root, "global.settings.pluginManagement.gradle")
if (initFile.exists()) {
initFile.delete()
}
initFile.appendText(PLUGIN_MANAGEMENT_SCRIPT)
initFile.appendText("gradle.apply plugin: com.kronos.plugin.version.PluginVersionGradlePlugin.class")
val fileList = mutableListOf<File>().apply {
addAll(target.gradle.startParameter.initScripts)
}
fileList.add(initFile)
target.gradle.startParameter.initScripts = fileList
}
fun getBuildTemp(root: File, path: String): File {
val result = File(root.canonicalPath + File.separator + "build" + File.separator + path)
touch(result)
return result
}
private fun touch(file: File) {
if (!file.parentFile.exists()) {
file.parentFile.mkdirs()
}
}
}
这次我们非常的投机取巧,通过gradle.startParameter.initScripts 将我们手动生成的在build的initscript插入到全局的gradle.initScripts中去。这样我们就可以在所有符合构建的工程中都插入这个PluginVersionGradlePlugin了。
class PluginVersionGradlePlugin : Plugin<Gradle> {
override fun apply(target: Gradle) {
target.settingsEvaluated {
pluginManagement(DefaultPluginManagementAction(this))
GradlePluginsVersion().execute(this)
}
target.addBuildListener(object : BuildAdapter() {
override fun projectsEvaluated(gradle: Gradle) {
super.projectsEvaluated(gradle)
val rootProject = gradle.rootProject
rootProject.configurations.all {
resolutionStrategy {
dependencySubstitution {
all {
if (requested is ModuleComponentSelector) {
val selector = requested as ModuleComponentSelector
val group = selector.group
val module = selector.module
val p = rootProject.allprojects.find { p ->
p.group.toString() == group
&& p.name == module
}
if (p != null) {
Logger.debug("select $requested local project")
useTarget(project(p.path), "selected local project")
}
}
}
}
}
}
}
})
}
}
这部分代码就比较少了,插件内主要是通过target.addBuildListener添加一个projectsEvaluated的监听,然后给settings插入全局的PluginManagement以及对应的策略。
总结
有一说一,我还是从我大佬身上学习到不少很好玩的操作的,最近转到编译组了,做的内容其实挺有意思的,这部分也是从大佬的代码中剥离出来的。
我个人认为复合构建模式还是大于单工程include,不仅仅是因为简单的配置共享这些。还有一些天然的构建隔离,项目层级方面的,比如说互相引用的情况。
https://github.com/Leifzhang/GradleSample/blob/master/Plugin/plugin-version/build.gradle
欢迎光临!Gradle 如何定位和解决依赖冲突
介绍
在开发过程中,我们不仅要引入我们其他项目的jar包,同时随着业务的复杂度加深,也免不了要引入许多的第三方开源库,那么不可避免的会出现依赖冲突的错误。
如何定位依赖冲突
排除法
排除法很简单,但是很耗时,就是选择一个依赖一个依赖的注释、编译、看结果。
IDEA gradle可视化
idea给我们提供了一个依赖树,但树只是一个平面图,并不是十分的直观。

Gradle Task
Gradle提供了一个task:dependencies,这个task能在命令行中显示依赖树之间的依赖关系。双击执行后就能在命令行中打印相关的依赖信息了.可以看到不同的buildType的信息

除了UI点击之外,也可通过命令行的方式来获取依赖树。
# implementation 指定的buildType信息
./gradlew app:dependencies -q --configuration implementation
这里我提取一点:
annotationProcessor - Annotation processors and their dependencies for source set 'main'.
\--- org.projectlombok:lombok:1.18.4
apiElements - API elements for main. (n)
No dependencies
archives - Configuration for archive artifacts.
No dependencies
asciidoctor
+--- org.springframework.restdocs:spring-restdocs-asciidoctor -> 2.0.2.RELEASE
+--- org.asciidoctor:asciidoctorj:1.5.3.2
| +--- org.jruby:jruby-complete:1.7.21
| \--- com.beust:jcommander:1.35
\--- org.asciidoctor:asciidoctorj-groovy-dsl:1.0.0.preview2
+--- org.codehaus.groovy:groovy-all:1.8.9
\--- org.asciidoctor:asciidoctorj:1.5.1 -> 1.5.3.2 (*)
bootArchives - Configuration for Spring Boot archive artifacts.
No dependencies
implementation - Implementation only dependencies for source set 'main'. (n)
+--- project mbg-model (n)
+--- project mbg-mapper (n)
+--- project cmp-client (n)
compileOnly - Compile only dependencies for source set 'main'.
+--- org.springframework.boot:spring-boot-configuration-processor -> 2.1.1.RELEASE
\--- org.projectlombok:lombok:1.18.4
default - Configuration for default artifacts.
+--- com.github.xiaoymin:knife4j-spring-ui:2.0.1
+--- org.jsoup:jsoup:1.13.1
+--- io.springside:springside-utils:5.0.0-RC1
| +--- com.google.guava:guava:20.0 -> 23.0
| | +--- com.google.code.findbugs:jsr305:1.3.9 -> 3.0.1
| | +--- com.google.errorprone:error_prone_annotations:2.0.18
| | +--- com.google.j2objc:j2objc-annotations:1.1
| | \--- org.codehaus.mojo:animal-sniffer-annotations:1.14
| +--- org.apache.commons:commons-lang3:3.5 -> 3.8.1
| \--- org.slf4j:slf4j-api:1.7.22 -> 1.7.25
compile - Dependencies for source set 'main' (deprecated, use 'implementation' instead).
+--- com.github.xiaoymin:knife4j-spring-ui:2.0.1
+--- org.jsoup:jsoup:1.13.1
\--- io.springside:springside-utils:5.0.0-RC1
+--- com.google.guava:guava:20.0
+--- org.apache.commons:commons-lang3:3.5 -> 3.8.1
\--- org.slf4j:slf4j-api:1.7.22 -> 1.7.25
compileClasspath - Compile classpath for source set 'main'.
+--- com.github.xiaoymin:knife4j-spring-ui:2.0.1
+--- org.jsoup:jsoup:1.13.1
+--- io.springside:springside-utils:5.0.0-RC1
| +--- com.google.guava:guava:20.0 -> 23.0
| | +--- com.google.code.findbugs:jsr305:1.3.9 -> 2.0.1
| | +--- com.google.errorprone:error_prone_annotations:2.0.18
| | +--- com.google.j2objc:j2objc-annotations:1.1
| | \--- org.codehaus.mojo:animal-sniffer-annotations:1.14
| +--- org.apache.commons:commons-lang3:3.5 -> 3.8.1
| \--- org.slf4j:slf4j-api:1.7.22 -> 1.7.25
+--- org.springframework.boot:spring-boot-configuration-processor -> 2.1.1.RELEASE
+--- org.projectlombok:lombok:1.18.4
runtimeElements - Elements of runtime for main. (n)
No dependencies
runtimeOnly - Runtime only dependencies for source set 'main'. (n)
No dependencies
testAnnotationProcessor - Annotation processors and their dependencies for source set 'test'.
\--- org.projectlombok:lombok:1.18.4
testCompile - Dependencies for source set 'test' (deprecated, use 'testImplementation' instead).
+--- com.github.xiaoymin:knife4j-spring-ui:2.0.1
+--- org.jsoup:jsoup:1.13.1
\--- io.springside:springside-utils:5.0.0-RC1
+--- com.google.guava:guava:20.0
+--- org.apache.commons:commons-lang3:3.5 -> 3.8.1
\--- org.slf4j:slf4j-api:1.7.22 -> 1.7.25
testCompileClasspath - Compile classpath for source set 'test'.
+--- com.github.xiaoymin:knife4j-spring-ui:2.0.1
+--- org.jsoup:jsoup:1.13.1
+--- io.springside:springside-utils:5.0.0-RC1
| +--- com.google.guava:guava:20.0 -> 23.0
| | +--- com.google.code.findbugs:jsr305:1.3.9 -> 2.0.1
| | +--- com.google.errorprone:error_prone_annotations:2.0.18
| | +--- com.google.j2objc:j2objc-annotations:1.1
| | \--- org.codehaus.mojo:animal-sniffer-annotations:1.14
| +--- org.apache.commons:commons-lang3:3.5 -> 3.8.1
| \--- org.slf4j:slf4j-api:1.7.22 -> 1.7.25
testCompileOnly - Compile only dependencies for source set 'test'.
\--- org.projectlombok:lombok:1.18.4
testImplementation - Implementation only dependencies for source set 'test'. (n)
+--- org.springframework.boot:spring-boot-starter-test (n)
+--- org.mybatis.spring.boot:mybatis-spring-boot-starter-test:1.3.2 (n)
\--- org.springframework.restdocs:spring-restdocs-mockmvc (n)
testRuntime - Runtime dependencies for source set 'test' (deprecated, use 'testRuntimeOnly' instead).
+--- com.github.xiaoymin:knife4j-spring-ui:2.0.1
+--- org.jsoup:jsoup:1.13.1
\--- io.springside:springside-utils:5.0.0-RC1
+--- com.google.guava:guava:20.0
+--- org.apache.commons:commons-lang3:3.5 -> 3.8.1
\--- org.slf4j:slf4j-api:1.7.22 -> 1.7.25
testRuntimeClasspath - Runtime classpath of source set 'test'.
+--- com.github.xiaoymin:knife4j-spring-ui:2.0.1
+--- cn.ucloud.ufile:ufile-client-java:2.3.0 (*)
+--- io.kubernetes:client-java:5.0.0 (*)
+--- org.glassfish.jersey.core:jersey-client:2.11 (*)
+--- org.glassfish.jersey.media:jersey-media-json-jackson:2.11 (*)
+--- org.glassfish.jersey.core:jersey-common:2.11 (*)
+--- org.apache.commons:commons-lang3:3.8.1
+--- com.github.penggle:kaptcha:2.3.2
| +--- javax.servlet:javax.servlet-api:3.1.0 -> 4.0.1
| \--- com.jhlabs:filters:2.0.235-1
+--- com.google.guava:guava:23.0 (*)
+--- com.alibaba:fastjson:1.2.54
+--- com.alibaba:druid-spring-boot-starter:1.1.10
| +--- com.alibaba:druid:1.1.10
| +--- org.slf4j:slf4j-api:1.7.25
| \--- org.springframework.boot:spring-boot-autoconfigure:1.5.12.RELEASE -> 2.1.1.RELEASE (*)
+--- io.projectreactor:reactor-core:3.2.8.RELEASE
| \--- org.reactivestreams:reactive-streams:1.0.2
+--- org.apache.poi:poi-ooxml:3.17
| +--- org.apache.poi:poi:3.17
| | +--- commons-codec:commons-codec:1.10 -> 1.11
| | \--- org.apache.commons:commons-collections4:4.1
| +--- org.apache.poi:poi-ooxml-schemas:3.17
| | \--- org.apache.xmlbeans:xmlbeans:2.6.0
| | \--- stax:stax-api:1.0.1
| \--- com.github.virtuald:curvesapi:1.04
+--- com.squareup.okhttp3:okhttp:3.14.7 (*)
+--- mysql:mysql-connector-java:6.0.6
+--- org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.2 (*)
+--- com.qcloud:cos_api:5.6.0 (*)
+--- com.github.pagehelper:pagehelper-spring-boot-starter:1.2.10 (*)
+--- tk.mybatis:mapper-spring-boot-starter:2.1.5
| +--- org.springframework.boot:spring-boot-starter:2.1.1.RELEASE (*)
| +--- org.springframework.boot:spring-boot-starter-jdbc:2.1.1.RELEASE (*)
| +--- org.mybatis:mybatis:3.4.6
| +--- org.mybatis:mybatis-spring:1.3.2
| +--- tk.mybatis:mapper-core:1.1.5
| | \--- javax.persistence:persistence-api:1.0
| +--- tk.mybatis:mapper-base:1.1.5
| | \--- javax.persistence:persistence-api:1.0
| +--- tk.mybatis:mapper-weekend:1.1.5
| +--- tk.mybatis:mapper-spring:1.1.5
| +--- tk.mybatis:mapper-extra:1.1.5
| +--- tk.mybatis:mapper-spring-boot-autoconfigure:2.1.5
| | +--- org.springframework.boot:spring-boot-autoconfigure:2.1.1.RELEASE (*)
| | +--- junit:junit:4.12 (*)
| | \--- org.hsqldb:hsqldb:2.4.1
| +--- junit:junit:4.12 (*)
| \--- org.hsqldb:hsqldb:2.4.1
+--- org.springframework.boot:spring-boot-devtools -> 2.1.1.RELEASE
| +--- org.springframework.boot:spring-boot:2.1.1.RELEASE (*)
| \--- org.springframework.boot:spring-boot-autoconfigure:2.1.1.RELEASE (*)
+--- org.springframework.boot:spring-boot-starter-web -> 2.1.1.RELEASE
| +--- org.springframework.boot:spring-boot-starter:2.1.1.RELEASE (*)
| +--- org.springframework.boot:spring-boot-starter-json:2.1.1.RELEASE
| | +--- org.springframework.boot:spring-boot-starter:2.1.1.RELEASE (*)
| | +--- org.springframework:spring-web:5.1.3.RELEASE (*)
| | +--- com.fasterxml.jackson.core:jackson-databind:2.9.7 (*)
| | +--- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.7
| | | +--- com.fasterxml.jackson.core:jackson-core:2.9.7
| | | \--- com.fasterxml.jackson.core:jackson-databind:2.9.7 (*)
| | +--- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.7
| | | +--- com.fasterxml.jackson.core:jackson-annotations:2.9.0
| | | +--- com.fasterxml.jackson.core:jackson-core:2.9.7
| | | \--- com.fasterxml.jackson.core:jackson-databind:2.9.7 (*)
| | \--- com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.7
| | +--- com.fasterxml.jackson.core:jackson-core:2.9.7
| | \--- com.fasterxml.jackson.core:jackson-databind:2.9.7 (*)
| +--- org.springframework.boot:spring-boot-starter-tomcat:2.1.1.RELEASE
| | +--- javax.annotation:javax.annotation-api:1.3.2
| | +--- org.apache.tomcat.embed:tomcat-embed-core:9.0.13
| | +--- org.apache.tomcat.embed:tomcat-embed-el:9.0.13
| | \--- org.apache.tomcat.embed:tomcat-embed-websocket:9.0.13
| | \--- org.apache.tomcat.embed:tomcat-embed-core:9.0.13
| +--- org.hibernate.validator:hibernate-validator:6.0.13.Final (*)
| +--- org.springframework:spring-web:5.1.3.RELEASE (*)
| \--- org.springframework:spring-webmvc:5.1.3.RELEASE
| +--- org.springframework:spring-aop:5.1.3.RELEASE (*)
| +--- org.springframework:spring-beans:5.1.3.RELEASE (*)
| +--- org.springframework:spring-context:5.1.3.RELEASE (*)
| +--- org.springframework:spring-core:5.1.3.RELEASE (*)
| +--- org.springframework:spring-expression:5.1.3.RELEASE (*)
| \--- org.springframework:spring-web:5.1.3.RELEASE (*)
+--- org.springframework.boot:spring-boot-starter-amqp -> 2.1.1.RELEASE
| +--- org.springframework.boot:spring-boot-starter:2.1.1.RELEASE (*)
| +--- org.springframework:spring-messaging:5.1.3.RELEASE
| | +--- org.springframework:spring-beans:5.1.3.RELEASE (*)
| | \--- org.springframework:spring-core:5.1.3.RELEASE (*)
| \--- org.springframework.amqp:spring-rabbit:2.1.2.RELEASE
| +--- org.springframework.amqp:spring-amqp:2.1.2.RELEASE
| | +--- org.springframework:spring-core:5.1.3.RELEASE (*)
| | \--- org.springframework.retry:spring-retry:1.2.2.RELEASE
| | \--- org.springframework:spring-core:4.3.13.RELEASE -> 5.1.3.RELEASE (*)
| +--- com.rabbitmq:amqp-client:5.4.3
| | \--- org.slf4j:slf4j-api:1.7.25
| +--- org.springframework:spring-context:5.1.3.RELEASE (*)
| +--- org.springframework:spring-messaging:5.1.3.RELEASE (*)
| \--- org.springframework:spring-tx:5.1.3.RELEASE (*)
testRuntimeOnly - Runtime only dependencies for source set 'test'. (n)
No dependencies
使用插件gradle-view
利用插件gradle-view可以直接通过面板的形式看到是哪个依赖库,具体是冲突了哪个版本。
插件地址:https://plugins.jetbrains.com/plugin/7150-gradle-view

如何解决冲突
删除其中一个jar包
删除其中一个jar包。
使用exclude来去除传递依赖
在知道是哪个库的哪些依赖的情况下,可以使用exclude来去除传递依赖,
exclude module:过滤模块
exclude group:过滤包名下所有依赖
如下:
implementation("com.qcloud:cos_api:5.6.0") {
exclude group: 'org.slf4j'
}
取消所有传递依赖
configurations.all {
transitive = false
}
强制依赖
对冲突的jar强行制定一个版本
gradleconfigurations.all {
resolutionStrategy.force "com.amazonaws:aws-java-sdk-bom:1.11.698"
}
gradle 跳过单元测试的3种方法
使用gradle构建工程时,如果想跳过单元测试,通常有3种方法:
1、在 build.gradle 文件的 test 中
test {
enabled(false)
// 或者 enable = false
}
2、在 gradle 命令中增加参数
gradle build -x test
3、 idea 中gradle构建时跳过单元测试
idea 不同版本的配置略有差异。

或者

Gradle多模块开发框架搭建(Springboot)
搭建过程
搭建环境:IDEA 2202.3.2
项目框架:Springboot3.0.2
项目名称:Muhammad
项目结构:Muh-app(子模块:项目启动入口,调取Muh-Design模块资源)、Muh-Design(子模块,设计模块)
1.原始状态
使用Spring Initializer创建项目,构建工具选择Gradle
项目创建成功后,目录结构为:
xxxxx
|— .gradle
|— .idea
|— gradle
|— wrapper:Gradle命令的包装,能够让机器在不安装Gradle的情况下运行程序,便于团队开发过程中统一Gradle构建版本
|— src
|— .gitignore
|— build.gradle:管理依赖包的配置文件(相当于Maven的pom.xml)
|— gradlew:Gradle命令的包装(Linux版),当机器上没有Gradle时,可以使用gradlew命令构建项目
|— gradlew.bat:Gradle命令的包装(Windows版),当机器上没有Gradle时,可以使用gradlew命令构建项目
|— HELP.md
|— settings.gradle:可以视为多模块项目总目录,Gradle通过该配置构建各模块,并组织模块间的关系
2.构建完成后,删除多余目录
删除src目录(父级项目不提供代码运行,仅用于模块管理)
3.创建子模块
- 创建子模块Muh-app:项目启动模块(统一入口)
- 创建子模块Muh-design:知识库-设计相关
- 删除两个子模块的多余文件和文件夹:
.gitignore、HELP.md、settings.gradle - 两个模块构建完成后,清空两个模块中
build.gradle配置文件的所有配置信息(子模块的相关配置以后可以在根项目的build.gradle配置文件中统一管理) - 删除子模块Muh-design的启动类
src/main/java/com/xfather/muhdesign/MuhDesignApplication.java和测试启动类src/test/java/com/xfather/muhdesign/MuhDesignApplicationTests.java
4.修改根项目的build.gradle文件
-
添加全局配置
allprojectsallprojects { // 将以下内容移动到allprojects配置中 group = 'com.xfather' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' targetCompatibility = '17' // 将plugins中的所有插件引入到全局配置中(根据默认初始化的plugins逐一添加) apply plugin:'java' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' repositories { mavenCentral() } } -
添加子模块配置
subprojects// 适用于子模块配置 subprojects { dependencies { implementation 'org.springframework.boot:spring-boot-starter' developmentOnly 'org.springframework.boot:spring-boot-devtools' testImplementation 'org.springframework.boot:spring-boot-starter-test' } } -
添加特定模块配置(各子模块个性化配置在这里添加)
// 特定项目配置 project(':Muh-app'){ dependencies { // Muh-app项目是Web应用启动入口,需要引入spring-boot-starter-web implementation 'org.springframework.boot:spring-boot-starter-web' // 添加项目依赖(给Muh-app项目引入Muh-design项目依赖) implementation project(':Muh-design') } } // 特定项目配置 project(':Muh-design'){ } -
删除多余的
task.name('test')配置 -
附:完整
build.gradle文件配置// 插件管理 plugins { id 'java' // springboot插件依赖 id 'org.springframework.boot' version '3.0.2' // 版本管理插件依赖 id 'io.spring.dependency-management' version '1.1.0' } // 全局配置管理(适用于所有模块【含子模块】) allprojects { group = 'com.xfather' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' targetCompatibility = '17' apply plugin:'java' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' repositories { mavenCentral() } } // 适用于子模块配置 subprojects { dependencies { implementation 'org.springframework.boot:spring-boot-starter' developmentOnly 'org.springframework.boot:spring-boot-devtools' testImplementation 'org.springframework.boot:spring-boot-starter-test' } } // 特定项目配置 project(':Muh-app'){ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' // 添加项目依赖(声明对Muh-design模块的依赖) implementation project(':Muh-design') } } // 特定项目配置 project(':Muh-design'){ }
5.修改根项目的settings.gradle配置文件
引入项目引用,增加以下配置
// 此处要按照加载顺序依次配置
include('Muh-design','Muh-app')
6.在Muh-design模块中创建测试服务
- 创建
com.xfather.muhdesign.service.TestService - 添加测试服务
public String hello(){ return "Hello,I'm Muh-design"; } - 给
TestService增加@Service注解
7.在Muh-app模块中创建测试控制
- 创建
com.xfather.muhapp.controller.TestController - 添加测试调用
TestService service; TestController(TestService service){ this.service = service; } @GetMapping("hello") public String hello(){ return service.hello(); } - 给
TestController增加@RestController注解
8.修改Springboot包扫描
因为Springboot无法自动识别其他模块下的类,因此需要手动处理,有三种方法:
- 第一种:使用
@Import导入对应的类
如:在controller中增加@Import(TestService.class) - 第二种:在
@SpringBootApplication上增加scanBasePackageClasses设定
即:@SpringBootApplication(scanBasePackageClasses = {TestService.class}) - 第三种:在
@SpringBootApplication上增加scanBasePackage设定
即:@SpringBootApplication(scanBasePackages = "com.xfather")
9.启动测试
启动MuhAppApplication,访问 http://127.0.0.1:8080/hello 即可看到运行结果
常见问题
-
Task ‘prepareKotlinBuildScriptModel’ not found in project:
问题原因:Gradle的某些版本中可能存在该问题,怀疑与Kotlin插件有关
解决办法一:在build.gradle文件中增加一个空的task来掩盖这个问题task prepareKotlinBuildScriptModel {}或
tasks.register("prepareKotlinBuildScriptModel"){}解决办法二:禁用IDEA的Kotlin插件
文件 ——> 设置 ——> 插件 ——> 已安装 ——> 禁用Kotlin -
无法自动装配,未找到"XXX"类型的Bean
问题原因:因为Springboot无法自动识别其他模块下的类,因此需要手动处理,有三种方法:
解决方法一:在对应controller上使用@Import导入对应的类如:在controller中增加`@Import(TestService.class)`解决方法二:在
@SpringBootApplication上增加scanBasePackageClasses设定即:`@SpringBootApplication(scanBasePackageClasses = {TestService.class})`解决方法三:在
@SpringBootApplication上增加scanBasePackage设定即:`@SpringBootApplication(scanBasePackages = "com.xfather")` -
Gradle如何打包和测试
测试:
在IDEA右侧Gradle面板中打开待测试项目,依次分别为:Tasks ——> verification ——> test即可进行测试
打包:
在IDEA右侧Gradle面板中打开待打包项目,依次分别为:Tasks ——> build ——> bootJar即可进行打包,打包完成后会生成到该项目build/libs目录下 -
提交git报错:does not have a commit checked out
问题原因:子模块创建时,同时创建了.git隐藏文件夹,导致子模块被识别为独立管理的版本
解决办法:删除子模块下.git文件夹重新提交即可
Gradle配置全局替换国内镜像 (2024版) 操作指南_gradle 国内镜像-CSDN博客
在中国,由于网络环境的影响,使用 Gradle 下载依赖库和插件时经常遭遇超时和连接失败的问题。为了解决这一问题,使用国内的镜像源来替代默认的官方源显得尤为重要。本文将详细介绍如何在 Gradle 中配置全局替换国内镜像,以及在具体操作过程中的注意事项和实用案例,帮助您在开发中高效切换网络源。
一、Gradle 基础知识
1. 什么是 Gradle
Gradle 是一种基于 JVM 的构建工具,广泛用于 Android 和现代 Java 项目的构建、依赖管理等。在 Gradle 中,您可以使用 build.gradle 文件配置项目的依赖、插件、任务等。
2. Gradle 如何获取依赖
Gradle 包管理依赖主要通过 Maven 仓库。默认情况下,它会从官方 Maven 中央仓库(https://repo.maven.apache.org/maven2)以及谷歌的 Maven 仓库(https://dl.google.com/dl/android/maven2)下载所需依赖。但是,因网络环境的原因,这些源在中国可能会非常慢甚至无法访问。
二、使用国内镜像源
为了提升 Gradle 的下载速度,可以使用国内一些托管 Maven 仓库的源,如阿里云、清华大学等。在这个指南中,我们将重点介绍如何使用阿里云的 Maven 镜像。
1. 阿里云 Maven 镜像地址
阿里云提供的 Maven 镜像地址如下:
https://maven.aliyun.com/repository/public
其他常用的国内镜像源还包括:
- 清华大学开源软件镜像站:https://mirrors.tuna.tsinghua.edu.cn
- 中科大镜像:https://mirrors.ustc.edu.cn
三、配置步骤
1. 找到您的 Gradle 用户目录
在开始配置之前,您需要知道 Gradle 的用户目录。一般情况下,Gradle 用户目录如下:
- Windows:
C:\Users\<YourUsername>\.gradle - macOS 和 Linux:
~/.gradle
2. 编辑 Gradle 配置文件
-
进入 Gradle 用户目录,找到或创建名为
gradle.properties的文件。该文件用于配置 Gradle 的全局属性。-
cd ~/.gradle
-
touch gradle.properties # 在 Linux/macOS 下创建文件
在 Windows 下,您可以直接使用文本编辑器创建该文件。
-
-
使用文本编辑器打开
gradle.properties文件,并添加如下配置:-
# 阿里云 Maven 镜像
-
repositories.grails.default = https://maven.aliyun.com/repository/public
-
# Optional, you can add other sources
-
repositories.grails.default.1 = https://mirrors.tuna.tsinghua.edu.cn/maven/repos/public
-
# Optional, adding Central repository
-
repositories.grails.default.2 = https://repo.maven.apache.org/maven2
-
3. 完整配置示例
以下是一个完整的 gradle.properties 文件示例:
-
# gradle.properties 示例配置
-
-
# 使用阿里云 Maven 镜像
-
repositories.grails.default = https://maven.aliyun.com/repository/public
-
repositories.grails.default.1 = https://mirrors.tuna.tsinghua.edu.cn/maven/repos/public
-
repositories.grails.default.2 = https://repo.maven.apache.org/maven2
-
-
# 其他可能的配置
-
systemProp.http.proxyHost=127.0.0.1
-
systemProp.http.proxyPort=1080
-
systemProp.https.proxyHost=127.0.0.1
-
systemProp.https.proxyPort=1080
4. 配置清华大学和中科大的 Maven 镜像
如果您选择使用清华大学的镜像,可以将 gradle.properties 文件设置如下:
-
# 使用清华大学的 Maven 镜像
-
repositories.grails.default = https://mirrors.tuna.tsinghua.edu.cn/maven/repos/public
对于中科大的镜像:
-
# 使用中科大的 Maven 镜像
-
repositories.grails.default = https://mirrors.ustc.edu.cn/maven/
四、测试配置
1. 创建一个简单的 Gradle 项目
为了验证配置是否成功,您可以创建一个简单的 Gradle 项目。
-
创建并进入新的项目目录:
-
mkdir test-gradle
-
cd test-gradle
-
-
初始化 Gradle 项目:
gradle init按照提示,选择类型为“basic”并完成初始化。
2. 修改 build.gradle 文件
在 test-gradle 目录下,找到 build.gradle 文件,编辑其内容如下:
-
plugins {
-
id 'java'
-
}
-
-
repositories {
-
mavenCentral()
-
}
-
-
dependencies {
-
implementation 'org.apache.commons:commons-lang3:3.12.0'
-
}
-
-
task hello {
-
doLast {
-
println 'Hello, Gradle!'
-
}
-
}
3. 构建项目
在命令行中运行以下命令来构建项目:
gradle build
如果所有配置正确,Gradle 将自动从您设置的国内镜像中下载依赖库,并顺利构建项目。
4. 运行自定义任务
在构建完成后,可以运行我们在 build.gradle 文件中定义的 hello 任务以查看输出:
gradle hello
您应该能看到以下输出:
-
> Task :hello
-
Hello, Gradle!
五、性能测试与优化建议
1. 下载速度测试
在您配置好镜像后,可以通过不同项目的下载速度来评估这些镜像的性能。可以试着多次执行 gradle build 命令,并记录所需时间。一般情况下,使用国内镜像后,下载速度会显著提升。
2. 脚本化配置
为了避免每次新建项目都需要手动添加镜像配置,可以通过创建一个脚本来自动化此过程。为此,可以使用 Bash 脚本:
-
-
-
# 创建 gradle.properties 文件并添加阿里云镜像配置
-
cat <<EOT >> ~/.gradle/gradle.properties
-
# Gradle 配置阿里云镜像
-
repositories.grails.default = https://maven.aliyun.com/repository/public
-
EOT
-
-
echo "Gradle 配置已更新为阿里云镜像!"
代码解读
将上述脚本保存为 setup_gradle_mirrors.sh 并给予执行权限:
chmod +x setup_gradle_mirrors.sh
执行脚本以快速配置:
./setup_gradle_mirrors.sh
通过本文的详细指导,您连同实际操作案例配置了 Gradle 的全局替换国内镜像。使用国内镜像源可以显著提高依赖下载速度,从而提高开发效率。建议您在实际开发工作中根据需要选择合适的镜像源,并整合到您的常用工程配置中。
此外,定期关注所用镜像源的性能和可用性,以确保您的开发环境始终保持高效。希望本文能为您提供实际的帮助,提升您的 Gradle 使用体验。对于任何深入的问题或细节,欢迎参与社区讨论或查阅相关资料以获得进一步的信息和支持。
四、init.gradle
说明:由于gradle构建时默认是从中央仓库中去查找依赖,中央仓库一般都在国外,速度很慢;我们可以执行构建时查找以来的顺序,进入gradle的文件夹内找到init.d文件夹后创建init.gradle(初始化构建依赖)添加如下内容,构建顺序按照mavenLocal() 本地仓库、 阿里云远端仓库、maven中央仓库;
-
allprojects {
-
repositories {
-
mavenLocal()
-
maven { name "Alibaba" ; url "https://maven.aliyun.com/repository/public" }
-
maven { name "Bstek" ; url "https://nexus.bsdn.org/content/groups/public/" }
-
mavenCentral()
-
}
-
buildscript {
-
repositories {
-
maven { name "Alibaba" ; url 'https://maven.aliyun.com/repository/public' }
-
maven { name "Bstek" ; url 'https://nexus.bsdn.org/content/groups/public/' }
-
maven { name "M2" ; url 'https://plugins.gradle.org/m2/' }
-
}
-
}
-
}
多个模块,如下
-
// 为指定父模块的名称 平台根
-
rootProject.name = 'project-root'
-
//包含子系统以及模块
-
include ':project-core'
-
//Hello系统模块的加载
-
include ':project-hello'
七、build.gradle 依赖管理简介
-
dependencies {
-
implementation 'org.springframework.boot:spring-boot-starter-web'
-
implementation 'mysql:mysql-connector-java:8.0.31'
-
implementation 'com.baomidou:mybatis-plus:3.5.3.2'
-
testImplementation 'org.springframework.boot:spring-boot-starter-test'
-
}
代码解读
maven 只有 compile、provided、test、runtime 这四种 scope
1、implementation: 默认的scope。implementation的作用域会让依赖在编译和运行时均包含在内,但是不会暴露在类库使用者的编译时。 举例,如果我们的类库包含了gson,那么其他人使用我们的类库时,编译时不会出现gson的依赖。
2、api:和implementation类似,都是编译和运行时都可见的依赖。但是api允许我们将自己类库的依赖暴露给我们类库的使用者。
3、compileOnly 和 runtimeOnly:这两种顾名思义,一种只在编译时可见,一种只在运行时可见。类似于 Maven的provided比较接近。
4、testImplementation:这种依赖在测试编译时和运行时可见,类似于Maven的test作用域。
5、testCompileOnly 和 testRuntimeOnly:这两种类似于compileOnly和runtimeOnly,但是作用于测试编译时和运行时。
使用gradle构建工程时,可以使用-x 命令进行跳过,类似maven的Skip Test,具体配置如下:

点击运行构建时,控制台会出现如下命令,说明配置成功
Executing task 'build -x test'...

浙公网安备 33010602011771号