Gradle 仓库及插件依赖代理镜像加速设置,跳过测试

前言

Gradle 作为最常用的项目构建工具之一,Android 和 Java 相关的开发者在日常的工作中肯定是经常打交道的。由于无形的墙或本地复杂的网络环境,会导致依赖编译工具依赖插件或库文件下载缓慢或直接无法下载,项目无法编译打包。这时我们就可以通过设置下载镜像来解决这些问题,我们可以选择配置成公司或自己搭建的 Maven 服务,或者是使用公有云服务商的 Maven 镜像服务,比如阿里云或腾讯云等。这里是以使用阿里云为例,自建和其他的也是类似的设置方式,只是仓库的地址不同。

如何判断依赖插件或库文件无法下载

通常情况下,文件下载不了 Gradle 会直接报错显示到控制台窗口,这种情况就很容易看出问题;但是,有时候 Gradle 并没有报错,一切都看似正常的执行,只是处理 进度一直不动 或卡在某个 Task 里,这时可能就是某些文件下不来导致的。如何查看呢?在项目根目录下执行 Gradle 的脚本任务时加上 --debug 就可以看到 Gradle 编译时执行步骤的详细信息,这里面就可以看到相关的下载信息,可能输出信息会有点多。

 
sh
代码解读
复制代码
# Windows 环境下执行
./gradlew.bat --debug

# *unix/Mac 环境下执行
./gradlew --debug
# 或
bash ./gradlew --debug

构建插件镜像加速

  • 全局配置

如果你没有设置 GRADLE_HOME 环境变量的话,默认情况下在用户目录下的 .gradle/ 文件夹下创建文件 init.gradle (这个文件默认是没有创建的,需手动创建),添加以下配置信息即可

 
groovy
代码解读
复制代码
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 文件中第一行加入,注意这配置必须要放在开头

 
groovy
代码解读
复制代码
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
 
groovy
代码解读
复制代码
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 项目也是类似
 
groovy
代码解读
复制代码
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 参数,这样可以看到相关依赖文件的下载链接地址,这样就可以判断文件是否是从镜像站下载的

 
bat
代码解读
复制代码
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
 
groovy
代码解读
复制代码
// 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,需放在开头

 
groovy
代码解读
复制代码
pluginManagement {
    repositories {
            maven { url "https://maven.aliyun.com/repository/gradle-plugin" }
            maven { url "https://maven.aliyun.com/repository/spring-plugin" }
            gradlePluginPortal()
    }
}
rootProject.name = 'player'

注意点

  • 全局配置和项目级配置的区别
  1. 全局配置是对所有有 Gradle 项目都生效的,但项目级的部分配置可能会覆盖全局的配置
  2. 项目级配置只对本项目生效,如部分项目需要配置 Maven 的私服可单独配置,并跟随git记录和提交
  • Gradle 版本兼容问题
  1. 如果采取了全局配置的方式,可能会有部分版本兼容问题,旧版本的 Gradle 可能不存在部分配置闭包无法识别问题,这是可以将 init.gradle 文件命名为其他名字即可,后续需要再重命名回来。

参考资料

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上呢?

奇怪的知识

接下来一个个知识点慢慢分析,然后让大家知道都干了些啥。

demo工程地址在这里

initscript

这个是gradle 藏的比较深的方法,正常情况下会放在.gradle目录下。官方demo如下。

代码语言:javascript
复制
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的。你可能不理解了,这个是什么啊。

代码语言:javascript
复制
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下添加一些通用的配置。

代码语言:javascript
复制
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的时候就会把对应的文件上传上去了。

代码语言:javascript
复制
gradlePlugin {
    plugins {
        settingsPlugin {
            // 在 app 模块需要通过 id 引用这个插件
            id = 'kronos.settings'
            // 实现这个插件的类的路径
            implementationClass = 'com.kronos.plugin.repo.RepoSettingsPlugin'
        }
    }
}

当然也有一些极端情况,比如一些插件已经好几个版本没有迭代了,本身也不支持这个特性的情况下,我们其实还是有另外一种方式的。

通过pluginManagement内的resolutionStrategy,之后通过name映射到具体的下载地址的方式,强行使用新的特性。

代码语言:javascript
复制
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看看我是咋写的呢。

代码语言:javascript
复制
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 将我们手动生成的在buildinitscript插入到全局的gradle.initScripts中去。这样我们就可以在所有符合构建的工程中都插入这个PluginVersionGradlePlugin了。

代码语言:javascript
复制
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
Gradle

这里我提取一点:

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
Shell

使用插件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'
    }
Gradle

取消所有传递依赖

configurations.all {
   transitive = false
}
Gradle

强制依赖

对冲突的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.创建子模块

  1. 创建子模块Muh-app:项目启动模块(统一入口)
  2. 创建子模块Muh-design:知识库-设计相关
  3. 删除两个子模块的多余文件和文件夹:.gitignoreHELP.mdsettings.gradle
  4. 两个模块构建完成后,清空两个模块中build.gradle配置文件的所有配置信息(子模块的相关配置以后可以在根项目的build.gradle配置文件中统一管理)
  5. 删除子模块Muh-design的启动类src/main/java/com/xfather/muhdesign/MuhDesignApplication.java和测试启动类src/test/java/com/xfather/muhdesign/MuhDesignApplicationTests.java

4.修改根项目的build.gradle文件

  1. 添加全局配置allprojects

    allprojects {
       // 将以下内容移动到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()
        }
    }
  2. 添加子模块配置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'
       }
    }
  3. 添加特定模块配置(各子模块个性化配置在这里添加)

    // 特定项目配置
    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'){
    
    }
  4. 删除多余的task.name('test')配置

  5. 附:完整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模块中创建测试服务

  1. 创建com.xfather.muhdesign.service.TestService
  2. 添加测试服务
    public String hello(){
         return "Hello,I'm Muh-design";
    }
  3. TestService增加@Service注解

7.在Muh-app模块中创建测试控制

  1. 创建com.xfather.muhapp.controller.TestController
  2. 添加测试调用
    TestService service;
    
    TestController(TestService service){
      this.service = service;
    }
    
    @GetMapping("hello")
    public String hello(){
      return service.hello();
    }
  3. TestController增加@RestController注解

8.修改Springboot包扫描

因为Springboot无法自动识别其他模块下的类,因此需要手动处理,有三种方法:

  1. 第一种:使用@Import导入对应的类
    如:在controller中增加@Import(TestService.class)
  2. 第二种:在@SpringBootApplication上增加scanBasePackageClasses设定
    即:@SpringBootApplication(scanBasePackageClasses = {TestService.class})
  3. 第三种:在@SpringBootApplication上增加scanBasePackage设定
    即:@SpringBootApplication(scanBasePackages = "com.xfather")

9.启动测试

启动MuhAppApplication,访问 http://127.0.0.1:8080/hello 即可看到运行结果

常见问题

  1. Task ‘prepareKotlinBuildScriptModel’ not found in project:
    问题原因:Gradle的某些版本中可能存在该问题,怀疑与Kotlin插件有关
    解决办法一:在build.gradle文件中增加一个空的task来掩盖这个问题

    task prepareKotlinBuildScriptModel {}

    tasks.register("prepareKotlinBuildScriptModel"){}

    解决办法二:禁用IDEA的Kotlin插件

    文件 ——> 设置 ——> 插件 ——> 已安装 ——> 禁用Kotlin
  2. 无法自动装配,未找到"XXX"类型的Bean
    问题原因:因为Springboot无法自动识别其他模块下的类,因此需要手动处理,有三种方法:
    解决方法一:在对应controller上使用@Import导入对应的类

    如:在controller中增加`@Import(TestService.class)`

    解决方法二:在@SpringBootApplication上增加scanBasePackageClasses设定

    即:`@SpringBootApplication(scanBasePackageClasses = {TestService.class})`

    解决方法三:在@SpringBootApplication上增加scanBasePackage设定

    即:`@SpringBootApplication(scanBasePackages = "com.xfather")` 
  3. Gradle如何打包和测试
    测试:
    在IDEA右侧Gradle面板中打开待测试项目,依次分别为:Tasks ——> verification ——> test即可进行测试
    打包:
    在IDEA右侧Gradle面板中打开待打包项目,依次分别为:Tasks ——> build ——> bootJar即可进行打包,打包完成后会生成到该项目build/libs目录下

  4. 提交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

其他常用的国内镜像源还包括:

三、配置步骤

1. 找到您的 Gradle 用户目录

在开始配置之前,您需要知道 Gradle 的用户目录。一般情况下,Gradle 用户目录如下:

  • Windows: C:\Users\<YourUsername>\.gradle
  • macOS 和 Linux: ~/.gradle

2. 编辑 Gradle 配置文件

  1. 进入 Gradle 用户目录,找到或创建名为 gradle.properties 的文件。该文件用于配置 Gradle 的全局属性。

     
    1. cd ~/.gradle
    2. touch gradle.properties # 在 Linux/macOS 下创建文件
     

    在 Windows 下,您可以直接使用文本编辑器创建该文件。

  2. 使用文本编辑器打开 gradle.properties 文件,并添加如下配置:

     
    1. # 阿里云 Maven 镜像
    2. repositories.grails.default = https://maven.aliyun.com/repository/public
    3. # Optional, you can add other sources
    4. repositories.grails.default.1 = https://mirrors.tuna.tsinghua.edu.cn/maven/repos/public
    5. # Optional, adding Central repository
    6. repositories.grails.default.2 = https://repo.maven.apache.org/maven2
     

3. 完整配置示例

以下是一个完整的 gradle.properties 文件示例:

 
  1. # gradle.properties 示例配置
  2.  
  3. # 使用阿里云 Maven 镜像
  4. repositories.grails.default = https://maven.aliyun.com/repository/public
  5. repositories.grails.default.1 = https://mirrors.tuna.tsinghua.edu.cn/maven/repos/public
  6. repositories.grails.default.2 = https://repo.maven.apache.org/maven2
  7.  
  8. # 其他可能的配置
  9. systemProp.http.proxyHost=127.0.0.1
  10. systemProp.http.proxyPort=1080
  11. systemProp.https.proxyHost=127.0.0.1
  12. systemProp.https.proxyPort=1080
 

4. 配置清华大学和中科大的 Maven 镜像

如果您选择使用清华大学的镜像,可以将 gradle.properties 文件设置如下:

 
  1. # 使用清华大学的 Maven 镜像
  2. repositories.grails.default = https://mirrors.tuna.tsinghua.edu.cn/maven/repos/public
 

对于中科大的镜像:

 
  1. # 使用中科大的 Maven 镜像
  2. repositories.grails.default = https://mirrors.ustc.edu.cn/maven/
 

四、测试配置

1. 创建一个简单的 Gradle 项目

为了验证配置是否成功,您可以创建一个简单的 Gradle 项目。

  1. 创建并进入新的项目目录:

     
    1. mkdir test-gradle
    2. cd test-gradle
     
  2. 初始化 Gradle 项目:

    gradle init

    按照提示,选择类型为“basic”并完成初始化。

2. 修改 build.gradle 文件

在 test-gradle 目录下,找到 build.gradle 文件,编辑其内容如下:

 
  1. plugins {
  2. id 'java'
  3. }
  4.  
  5. repositories {
  6. mavenCentral()
  7. }
  8.  
  9. dependencies {
  10. implementation 'org.apache.commons:commons-lang3:3.12.0'
  11. }
  12.  
  13. task hello {
  14. doLast {
  15. println 'Hello, Gradle!'
  16. }
  17. }
 

3. 构建项目

在命令行中运行以下命令来构建项目:

gradle build

如果所有配置正确,Gradle 将自动从您设置的国内镜像中下载依赖库,并顺利构建项目。

4. 运行自定义任务

在构建完成后,可以运行我们在 build.gradle 文件中定义的 hello 任务以查看输出:

gradle hello

您应该能看到以下输出:

 
  1. > Task :hello
  2. Hello, Gradle!
 

五、性能测试与优化建议

1. 下载速度测试

在您配置好镜像后,可以通过不同项目的下载速度来评估这些镜像的性能。可以试着多次执行 gradle build 命令,并记录所需时间。一般情况下,使用国内镜像后,下载速度会显著提升。

2. 脚本化配置

为了避免每次新建项目都需要手动添加镜像配置,可以通过创建一个脚本来自动化此过程。为此,可以使用 Bash 脚本:

 
  1. #!/bin/bash
  2.  
  3. # 创建 gradle.properties 文件并添加阿里云镜像配置
  4. cat <<EOT >> ~/.gradle/gradle.properties
  5. # Gradle 配置阿里云镜像
  6. repositories.grails.default = https://maven.aliyun.com/repository/public
  7. EOT
  8.  
  9. 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中央仓库;

 
  1. allprojects {
  2. repositories {
  3. mavenLocal()
  4. maven { name "Alibaba" ; url "https://maven.aliyun.com/repository/public" }
  5. maven { name "Bstek" ; url "https://nexus.bsdn.org/content/groups/public/" }
  6. mavenCentral()
  7. }
  8. buildscript {
  9. repositories {
  10. maven { name "Alibaba" ; url 'https://maven.aliyun.com/repository/public' }
  11. maven { name "Bstek" ; url 'https://nexus.bsdn.org/content/groups/public/' }
  12. maven { name "M2" ; url 'https://plugins.gradle.org/m2/' }
  13. }
  14. }
  15. }
 

多个模块,如下

 
  1. // 为指定父模块的名称 平台根
  2. rootProject.name = 'project-root'
  3. //包含子系统以及模块
  4. include ':project-core'
  5. //Hello系统模块的加载
  6. include ':project-hello'
 

 

七、build.gradle 依赖管理简介

 
  1. dependencies {
  2. implementation 'org.springframework.boot:spring-boot-starter-web'
  3. implementation 'mysql:mysql-connector-java:8.0.31'
  4. implementation 'com.baomidou:mybatis-plus:3.5.3.2'
  5. testImplementation 'org.springframework.boot:spring-boot-starter-test'
  6. }
代码解读

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 命令进行跳过,类似mavenSkip Test,具体配置如下:

 点击运行构建时,控制台会出现如下命令,说明配置成功

Executing task 'build -x test'...

 

 

 

posted @ 2025-01-07 11:37  CharyGao  阅读(6729)  评论(0)    收藏  举报