gradle使用教程,小白一篇就够-程序员宅基地

技术标签: gradle  开发环境工具安装  

概述

Gradle是新一代构建工具,从0.x版本一路走来虽然国内可寻的资料多了一些,但都是比较碎片化的知识。官方的Userguide虽然是业内良心之作,但无奈太长,且版本变化较快,又鉴于很多同学一看到英文内心便已认定无法读懂,遂打算利用业余时间攒此本《跟我学gradle》,希望通过此书可以降低学习曲线能让希望使用Gradle的同学更轻易地入门。

简介

Gradle是继Maven之后的新一代构建工具,它采用基于groovy的DSL语言作为脚本,相比传统构建工具通过XML来配置而言,最直观上的感受就是脚本更加的简洁、优雅。如果你之前对Maven有所了解,那么可以很轻易的转换到Gradle,它采用了同Maven一致的目录结构,可以与Maven一样使用Maven中央仓库以及各类仓库的资源,并且Gradle默认也内置了脚本转换命令可以方便的将POM转换为gradle.build。

Gradle的优势

依赖管理: 即将你项目中的jar包管理起来,你可以使用Maven或者Ivy的远程仓库、或者本地文件系统等

编译打包: 可以通过脚本实现花样打包,包括修改文件、添加抑或排除某些类或资源、采用指定JDK版本构建、打包后自动上传等等

多项目支持: Gradle对多项目有着良好的支持,比如一个很具有代表性的实践就是spring framework
多语言支持:无论是java、groovy、scala、c++都有良好的支持
跨平台支持:gradle是基于jvm的,只要有jvm你就可以让gradle运行
灵活的的脚本:你可以使用groovy灵活的编写任务完成你想要做的任何事情

约定优于配置
约定优于配置(convention over configuration),简单而言就是遵循一定的固定规则从而可以避免额外的配置。虽然这一定程度上降低了灵活性,但却能减少重复的额外配置,同时也可以帮助开发人员遵守一定的规则。当然,约定并不是强制性约束,Gradle提供了各种灵活的途径可以让你更改默认的配置。

标准结构
Gradle遵循COC(convention over configuration约定优于配置)的理念,默认情况下提供了与maven相同的项目结构配置
大体结构如下

project root
src/main/java(测试)
src/main/resources
src/test/java(测试源码目录)
src/test/resources(测试资源目录)
src/main/webapp(web工程)

非标准结构配置

在一些老项目上,可能目录结构并不是标准结构,然而一般开发人员又不好进行结构调整.此时可以通过配置sourceSet来指定目录结构

sourceSets {
    
    main {
    
        java {
    
            srcDir 'src/java'
        }
        resources {
    
            srcDir 'src/resources'
        }
    }
}

或者采用如下写法也是可以的

sourceSets {
    
    main.java.srcDirs = ['src/java']
    main.resources.srcDirs = ['src/resources']
}

在android中

android {
    
    sourceSets {
    
        main {
    
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        androidTest.setRoot('tests')
    }
}

当然如果你的资源目录与源码目录相同这样就比较…了,但你仍然可以按照如下方式搭配include和exclude进行指定

sourceSets {
    
  main {
    
    java {
    
      //your java source paths and exclusions go here...
    }

    resources {
    
      srcDir 'main/resources'
      include '**/*.properties'
      include '**/*.png'


      srcDir 'src'
      include '**/Messages*.properties'
      exclude '**/*.java'
    }
  }
}

一个简单的Gralde脚本,或许包含如下内容,其中标明可选的都是可以删掉的部分

插件引入:声明你所需的插件
属性定义(可选):定义扩展属性
局部变量(可选):定义局部变量
属性修改(可选):指定project自带属性
仓库定义:指明要从哪个仓库下载jar包
依赖声明:声明项目中需要哪些依赖
自定义任务(可选):自定义一些任务

//定义扩展属性(给脚本用的脚本)
buildScript {
    
    repositories {
    
         mavenCentral()
    }
}

//应用插件,这里引入了Gradle的Java插件,此插件提供了Java构建和测试所需的一切。
apply plugin: 'java'
//定义扩展属性(可选)
ext {
    
    foo="foo"
}
//定义局部变量(可选)
def bar="bar"

//修改项目属性(可选)
group 'pkaq'
version '1.0-SNAPSHOT'

//定义仓库,当然gradle也可以使用各maven库 ivy库 私服 本地文件等,后续章节会详细介绍(可选)
repositories {
    
    jcenter()
}

//定义依赖,这里采用了g:a:v简写方式,加号代表了最新版本(可选)
dependencies {
    
    compile "cn.pkaq:ptj.tiger:+"
}

//自定义任务(可选)
task printFoobar {
    
    println "${foo}__${bar}"
}

buildscript 配置该 Project 的构建脚本的 classpath,在 Andorid Studio 中的 root project 中可以看到
apply(options: Map<String, ?>)我们通过该方法使用插件或者是其他脚本,options里主要选项有:

  • from: 使用其他脚本,值可以为 Project.uri(Object) 支持的路径

  • plugin:使用其他插件,值可以为插件id或者是插件的具体实现类

apply plugin: 'com.android.application'
//使用插件,MyPluginImpl 就是一个Plugin接口的实现类
apply plugin: MyPluginImpl

//引用其他gradle脚本,push.gradle就是另外一个gradle脚本文件
apply from: './push.gradle'

扩展:
Gradle脚本是基于groovy的DSL,这里对上述脚本与Gradle api的关系稍作解释,希望可以帮助你更好的理解groovy与gradle dsl之间的关系

//project 的buildScript方法  实际返回的是一个ScriptHandler对象
buildScript {
    
    repositories {
    
         mavenCentral()
    }
}
//调用apply方法 参数是一个 map,调用时参数省略了括号
apply plugin: 'java'
//定义扩展属性(可选)
ext {
    
    foo="foo"
}
//定义局部变量(可选)
def bar="bar"

//修改项目属性(可选)
group 'pkaq'
version '1.0-SNAPSHOT'

//project 的repositories 方法  实际返回的是一个RepositoryHandler对象
repositories {
    
    jcenter()
}

//project 的dependencies 方法  实际返回的是一个DependencyHandler对象
dependencies {
    
    compile "cn.pkaq:ptj.tiger:+"
}

//调用Task task(String name, Closure configureClosure)方法
task printFoobar {
    
    println "${foo}__${bar}"
}

什么是依赖管理?

通常而言,依赖管理包括两部分,对依赖的管理以及发布物的管理;依赖是指构建项目所需的构件(jar包等)。例如,对于一个应用了spring普通的java web项目而言,spring相关jar包即项目所需的依赖。发布物,则是指项目产出的需要上传的项目产物。

采用变量统一控制版本号

dependencies {
    
    def bootVersion = "1.3.5.RELEASE"
    compile     "org.springframework.boot:spring-boot-starter-web:${bootVersion}",  
                "org.springframework.boot:spring-boot-starter-data-jpa:${bootVersion}",
                "org.springframework.boot:spring-boot-starter-tomcat:${bootVersion}"
}

自动获取最新版本依赖

如果你想某个库每次构建时都检查是否有新版本,那么可以采用+来让Gradle在每次构建时都检查并应用最新版本的依赖。当然也可以采用1.x,2.x的方式来获取某个大版本下的最新版本。

dependencies {
    
    compile     "org.springframework.boot:spring-boot-starter-web:+"
}

依赖的坐标

仓库中构件(jar包)的坐标是由configurationName
"group:name:version:classifier@extension"组成的字符串构成,如同Maven中的GAV坐标,Gradle可借由此来定位你想搜寻的jar包。

在gradle中可以通过以下方式来声明依赖:

testCompile group: 'junit', name: 'junit', version: '4.0'

在gradle中可以通过以下方式来声明依赖:

testCompile group: 'junit', name: 'junit', version: '4.0'

在这里插入图片描述

这是由于Gradle依赖配置支持多种书写方式,采用map或者字符串。

// 采用map描述依赖
testCompile group: 'junit', name: 'junit', version: '4.0'
// 采用字符串方式描述依赖
testCompile 'junit:junit:4.0'

显然采用字符串的方式更加简单直观,当然借助groovy语言强大的GString还可以对版本号进行抽离。如下面的示例,这里需要注意的是如果要用GString的话,依赖描述的字符串要用""双引号包起来才会生效。

def ver = "4.0"
testCompile "junit:junit:${ver}"

依赖的范围

上面的例子中采用的testComplie是声明依赖的作用范围,关于各种作用范围的功效可见下表。

tip:这里需要注意的是,provided范围内的传递依赖也不会被打包

在这里插入图片描述

依赖的分类

在这里插入图片描述

外部依赖

可以通过如下方式声明外部依赖,Gradle支持通过map方式或者g️v的简写方式传入依赖描述,这些声明依赖会去配置的repository查找。

dependencies {
    
 // 采用map方式传入单个
  compile group: 'commons-lang', name: 'commons-lang', version: '2.6'
 // 采用map方式传入多个
  compile(
      [group: 'org.springframework', name: 'spring-core', version: '2.5'],
      [group: 'org.springframework', name: 'spring-aop', version: '2.5']
  )
  // 采用简写方式声明
  compile 'org.projectlombok:lombok:1.16.10' 
  // 采用简写方式传入多个 
  compile 'org.springframework:spring-core:2.5',
          'org.springframework:spring-aop:2.5'

}

项目依赖

此类依赖多见于多模块项目,书写方式如下,其中:是基于跟项目的相对路径描述符。

 compile project(':project-foo')

文件依赖

依赖存在于本地文件系统中,举个栗子,如oracle的OJDBC驱动,中央仓库中没有又没有自建私服此时需要放到项目lib下进行手工加载那么便可采用此种方式,可以通过FileCollection接口及其子接口提供的方法加载这些依赖(支持文件通配符)

dependencies {
    
   // 指定多个依赖
   compile files('hibernate.jar', 'libs/spring.jar')

   // 读取lib文件夹下的全部文件作为项目依赖
   compile fileTree('libs')

   // 根据指定基准目录\包含\排除条件加载依赖
   compile fileTree(dir:'libs',include:'spring*.jar',exclude:'hibernate*.jar')
 }

内置依赖

跟随Gradle发行包或者基于Gradle API的一些依赖,通常在插件开发时使用,当前提供了如下三种

 dependencies {
    
   // 加载Gradle自带的groovy作为依赖
   compile localGroovy()

   // 使用Gradle API作为依赖
   compile gradleApi()

   /使用 Gradle test-kit API 作为依赖
   testCompile gradleTestKit()
 }

子模块依赖

简单来说就是声明依赖的依赖或者依赖的传递依赖,一般情况下如果依赖的库并未用构建工具构建(尤其是一些上古时代的老库),那么Gradle是无法透过源文件去查找该库的传递性依赖的,通常而言,一个模块采用XML(POM文 件)来描述库的元数据和它的传递性依赖。Gradle可以借由此方式提供相同的能力,当然这种方式也会可以改写原有的传递性依赖。这里让druid连接池依赖了ptj.tiger的一个库。

dependencies {
    
    // 让ptj.tiger作为druid的传递性依赖
    compile module("com.alibaba:druid:1.0.26") {
    
            dependency("cn.pkaq:ptj.tiger:+")
    }

    runtime module("org.codehaus.groovy:groovy:2.4.7") {
    
        // 停用groovy依赖的commons-cli库的依赖传递
        dependency("commons-cli:commons-cli:1.0") {
    
            transitive = false
        }
        // 让groovy依赖的ant模块的依赖ant-launcher停用传递性依赖并依赖ant-junit..........
        module(group: 'org.apache.ant', name: 'ant', version: '1.9.6') {
    
            dependencies "org.apache.ant:ant-launcher:1.9.6@jar",
                         "org.apache.ant:ant-junit:1.9.6"
        }
    }
 }

什么是传递依赖?

在Maven仓库中,构件通过POM(一种XML文件)来描述相关信息以及传递性依赖。Gradle 可以通过分析 该文件获取获取所以依赖以及依赖的依赖和依赖的依赖的依赖,为了更加直观的表述,可以通过下面的输出 结果了解。

在这里插入图片描述

可以看到,我们的项目依赖了com.android.support-v4包,然而com.android.support-v4包却依赖了一众support的全家桶,借助Gradle的传递性依赖特性,你无需再你的脚本中把这些依赖都声明一遍,你只需要简单的一行,Gradle便会帮你将传递性依赖一起下载下来。

传递依赖特性可以轻松地通过transitive参数进行开启或关闭,上面的示例中如果要忽略com.android.support-v4的传递性依赖可以采用指定 transitive = false 的方式来关闭依赖传递特性,也可以采用添加@jar的方式忽略该依赖的所有传递性依赖。

 compile('com.android.support:support-v4:23.1.1'){
    
        transitive = false
 }

 compile 'com.android.support:support-v4:23.1.1'@jar

当然,你也可以全局性的关闭依赖的传递特性。

 configurations.all {
    
   transitive = false
}

排除依赖

有些时候你可能需要排除一些传递性依赖中的某个模块,此时便不能靠单纯的关闭依赖传递特性来解决了。这时exclude就该登场了,如果说@jar彻底的解决了传递问题,那么exclude则是部分解决了传递问题。然而实际上exclude肯能还会用的频率更更频繁一些,比如下面几种情况。

可以通过configuration配置或者在依赖声明时添加exclude的方式来排除指定的引用。

exclude可以接收group和module两个参数,这两个参数可以单独使用也可以搭配使用,具体理解如下:

compile('com.github.nanchen2251:CompressHelper:1.0.5'){
    
        //com.android.support:appcompat-v7:23.1.1
        exclude group: 'com.android.support'//排除组织依赖
        exclude module: 'appcompat-v7'//排除模块依赖
 }

强制使用版本

当然,有时候你可能仅仅是需要强制使用某个统一的依赖版本,而不是排除他们,那么此时force就该登场了。指定force = true属性可以冲突时优先使用该版本进行解决

compile('com.github.nanchen2251:CompressHelper:1.0.5'){
    
        force = true
 }

全局配置强制使用某个版本的依赖来解决依赖冲突中出现的依赖

configurations.all {
    
   resolutionStrategy {
    
       force 'com.github.nanchen2251:CompressHelper:1.0.5'
   }
}

另一个例子:

//解决冲突 同一版本
configurations.all {
    
    resolutionStrategy.eachDependency {
     DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support') {
    
            if (requested.name.startsWith("support-")||
                    requested.name.startsWith("animated")||
                    requested.name.startsWith("cardview")||
                    requested.name.startsWith("design")||
                    requested.name.startsWith("gridlayout")||
                    requested.name.startsWith("recyclerview")||
                    requested.name.startsWith("transition")||
                    requested.name.startsWith("appcompat")) {
    
                details.useVersion '25.0.0'
            }
        }
    }
}

使用动态版本

如果你想让你的工程始终采用最新依赖,那么Gradle提供了一种方式可以始终保证采用依赖的最新版本而无需每次手工检查修改版本。

使用加号+,可以让Gradle在每次执行构建时检查远程仓库是否存在该依赖的新版本,如果存在新版本则下载选用最新版本。当然也可以指定依赖某个大版本下的最新子版本,1.+表示始终采用该依赖最新的1.x版本的最新依赖。

  compile 'com.android.support:support-v4:+'//下载最新
  compile 'com.android.support:support-v4:23+'//基于23这个版本最新

虽然这是看上去十分风骚的一种用法,但这无疑会降低你系统构建的速度同时提高构建失败的风险。因为Gradle不得不每次检查远程仓库是否存在最新版本,同时新版本也可能带来无法预知的兼容性问题。

一个综合案例

compile('com.github.nanchen2251:CompressHelper:1.0.5') {
    
   // 冲突时优先使用该版本
   force = true

   // 依据构建名称排除
   exclude module: 'CompressHelper' 
   // 依据组织名称排除
   exclude group: 'com.github.nanchen2251' 
   // 依据组织名称+构件名称排除
   exclude group: 'com.github.nanchen2251', module: 'CompressHelper' 

   // 为本依赖关闭依赖传递特性
   transitive = false
}

使用config.gradle文件统一管理项目依赖

  1. 在项目的根目录下创建config.gradle文件

在这里插入图片描述

  1. 编辑 config.gradle,定义项目依赖

在app的build.gradle中,我们通常需要配置两个部分

Android 目录下的项目的版本/包名/编译版本等信息 dependencies 目录下的安卓Support库和我们自己引用的第三方库
所以通常我们在config.gradle文件也将依赖分成两个部分 android/dependencies

ext {
    

    android = [
            compileSdkVersion      : 28,
            buildToolsVersion      : "28.0.0",
            applicationId          : "com.will.weiyue",
            minSdkVersion          : 19,
            targetSdkVersion       : 28,
            versionCode            : 1,
            versionName            : "1.0"
    ]
    //因为support库都是同一个版本,单独拎出来,方便修改
    dependVersion = [
            support: "28.0.0-alpha3"
    ]

    dependencies = [
            // android-support
            "support-v4"            : "com.android.support:support-v4:${dependVersion.support}",
            "appcompat-v7"          : "com.android.support:appcompat-v7:${dependVersion.support}",
            "design"                : "com.android.support:design:${dependVersion.support}",
            "recyclerview"          : "com.android.support:recyclerview-v7:${dependVersion.support}",
            "cardview"              : "com.android.support:cardview-v7:${dependVersion.support}",
    ]
}

  1. 在 项目的 build.gradle文件中引用config.gradle文件
// 在项目build.gradle文件的最外层添加引用
apply from: "config.gradle"

  1. 修改app的build.gradle文件中的项目引用
// 将android 和 dependencies下的引用都指向 config.gradle
// rootProject.ext.android/dependencies  config.gradle文件的路径
android {
    
    compileSdkVersion rootProject.ext.android.compileSdkVersion
    defaultConfig {
    
        applicationId rootProject.ext.android.applicationId
        minSdkVersion rootProject.ext.android.minSdkVersion
        targetSdkVersion rootProject.ext.android.targetSdkVersion
        versionCode rootProject.ext.android.versionCode
        versionName rootProject.ext.android.versionName
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
    
        release {
    
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation rootProject.ext.dependencies["appcompat-v7"]
    implementation rootProject.ext.dependencies["constraint-layout"]
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

更新依赖

在执行build、compile等任务时会解析项目配置的依赖并按照配置的仓库去搜寻下载这些依赖。默认情况下,Gradle会依照Gradle缓存->你配置的仓库的顺序依次搜寻这些依赖,并且一旦找到就会停止搜索。如果想要忽略本地缓存每次都进行远程检索可以通过在执行命令时添加–refresh-dependencies参数来强制刷新依赖。

gradle build --refresh-dependencies

当远程仓库上传了相同版本依赖时,有时需要为缓存指定一个时效去检查远程仓库的依赖笨版本,Gradle提供了cacheChangingModulesFor(int, java.util.concurrent.TimeUnit) ,cacheDynamicVersionsFor(int, java.util.concurrent.TimeUnit)两个方法来设置缓存的时效

configurations.all {
    
    //每隔24小时检查远程依赖是否存在更新
    resolutionStrategy.cacheChangingModulesFor 24, 'hours'
    //每隔10分钟..
    //resolutionStrategy.cacheChangingModulesFor 10, 'minutes'
    // 采用动态版本声明的依赖缓存10分钟
    resolutionStrategy.cacheDynamicVersionsFor 10*60, 'seconds'
}

dependencies {
    
    // 添加changing: true
    compile group: "group", name: "module", version: "1.1-SNAPSHOT", changing: true
    //简写方式
    //compile('group:module:1.1-SNAPSHOT') { changing = true }
}

缓存管理

缓存位置管理

Gradle在按照配置的仓库去搜寻下载依赖时,下载的依赖默认会缓存到USER_HOME/.gradle/caches目录下,当然也可以手工修改这个位置。
  具体可以参考如下三种方式:

  • 通过添加系统变量 GRADLE_USER_HOME
  • 设置虚拟机参数 org.gradle.user.home 属性
  • 通过命令行-g或者 --gradle-user-home 参数设置

离线模式(总是采用缓存内容)

Gradle提供了一种离线模式,可以让你构建时总是采用缓存的内容而无需去联网检查,如果你并未采用动态版本特性且可以确保项目中依赖的版本都已经缓存到了本地,这无疑是提高构建速度的一个好选择。开启离线模式只需要在执行命令时候添加–offline参数即可。当然,采用这种模式的也是有代价的,如果缓存中搜寻不到所需依赖会导致构建失败。

gradle build --offline

依赖-构件的上传与发布

借助maven-publish插件可以轻松地将jar包发布到仓库中。这个过程没啥幺蛾子直接上代码吧。了解更多配置可以查看 Maven plugin插件章节

apply plugin: 'maven-publish'
apply plugin: 'java'

// 打包源文件
task sourceJar(type: Jar) {
    
    from sourceSets.main.allSource
    classifier = 'sources'
}

task javadocJar(type: Jar, dependsOn: javadoc) {
    
    classifier = 'javadoc'
    from javadoc.destinationDir
}

publishing {
    
     // 目标仓库
    repositories {
    
        maven {
    
           url "xxx"
        }
    }   

    publications {
              
        mavenJava(MavenPublication) {
    
            // 设置gav属性
            groupId 'org.pkaq'
            artifactId 'tiger'
            version '1.1'

            from components.java
            artifact sourceJar

             // 设置pom相关信息
            pom.withXml {
    
                Node root = asNode()              
                root.appendNode('description', 'bazinga!')
            }
        }
    }

}
//生成一个元的pom文件
model {
    
    tasks.generatePomFileForMavenJavaPublication {
    
        destination = file("$buildDir/generated-pom.xml")
    }
}

检查依赖

在引用的依赖或传递性依赖存在版本冲突时,Gradle采用的策略是优先选取最新的依赖版本解决版本冲突问题。。如何知道哪些依赖传递了哪些子依赖,哪些传递的依赖又被Gradle进行了隐性升级呢。采用下面的命令可以查看各个范围的依赖树。

gradle  dependencies > dep.log

输出结果:

dependencies

------------------------------------------------------------
Root project
------------------------------------------------------------

archives - Configuration for archive artifacts.
No dependencies

compile - Dependencies for source set 'main'.
+--- org.springframework.boot:spring-boot-starter-web:1.4.2.RELEASE
|    +--- org.springframework.boot:spring-boot-starter:1.4.2.RELEASE
|    |    +--- org.springframework.boot:spring-boot:1.4.2.RELEASE
|    |    |    +--- org.springframework:spring-core:4.3.4.RELEASE
|    |    |    |    \--- commons-logging:commons-logging:1.2
|    |    |    \--- org.springframework:spring-context:4.3.4.RELEASE
|    |    |         +--- org.springframework:spring-aop:4.3.4.RELEASE
|    |    |         |    +--- org.springframework:spring-beans:4.3.4.RELEASE
|    |    |         |    |    \--- org.springframework:spring-core:4.3.4.RELEASE (*)
|    |    |         |    \--- org.springframework:spring-core:4.3.4.RELEASE (*)
|    |    |         +--- org.springframework:spring-beans:4.3.4.RELEASE (*)
|    |    |         +--- org.springframework:spring-core:4.3.4.RELEASE (*)
|    |    |         \--- org.springframework:spring-expression:4.3.4.RELEASE
....
....
省略的
....
....
\--- org.apache.tomcat.embed:tomcat-embed-jasper:8.5.4
     +--- org.apache.tomcat.embed:tomcat-embed-core:8.5.4 -> 8.5.6
     +--- org.apache.tomcat.embed:tomcat-embed-el:8.5.4 -> 8.5.6
     \--- org.eclipse.jdt.core.compiler:ecj:4.5.1

后面dep.log文件名可以随意,然而,你一定在想为什么有些带了()有的带了->有的什么都没有呢,这是什么鬼。前面已经说过,当发生版本冲突时Gradle会采用最新版本解决。仔细观察带了()的依赖你会发现这些依赖被不同的库重复依赖了若干次,这里(*)的意思即是表示该依赖被忽略掉了。而->则表示其它的定级依赖的传递依赖中存在更高版本的依赖,该版本将会使用->后面的版本来替代。

反向查找

如果你想知道某个依赖到底被哪个库引用过,可以采用下面的命令进行反向查找

gradle dependencyInsight  --dependency tomcat-embed-core > reverse.log 

示例如下:

:dependencyInsight
org.apache.tomcat.embed:tomcat-embed-core:8.5.6 (conflict resolution)
+--- org.apache.tomcat.embed:tomcat-embed-websocket:8.5.6
|    \--- org.springframework.boot:spring-boot-starter-tomcat:1.4.2.RELEASE
|         \--- org.springframework.boot:spring-boot-starter-web:1.4.2.RELEASE
|              \--- compile
\--- org.springframework.boot:spring-boot-starter-tomcat:1.4.2.RELEASE (*)

org.apache.tomcat.embed:tomcat-embed-core:8.5.4 -> 8.5.6
\--- org.apache.tomcat.embed:tomcat-embed-jasper:8.5.4
     \--- compile

(*) - dependencies omitted (listed previously)

BUILD SUCCESSFUL

Total time: 6.936 secs

上面的报告中可以看到8.5.6这个版本后面标注了(conflict resolution) 说明了该版本是用于解决冲突选用的版本。

冲突即停

Gradle默认采用自动升级版本的方式解决依赖冲突,有时这种隐式升级可能会带来一些不必要的麻烦,此时我们可以通过更改这种默认行为来让Gradle发现版本冲突时立即停止构建并抛出错误信息。
更改脚本:

configurations.all {
    
  resolutionStrategy {
    
    failOnVersionConflict()
  }
}

执行gradle build的输出结果:

:compileJava FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Could not resolve all dependencies for configuration ':compileClasspath'.
> A conflict was found between the following modules:
   - org.apache.tomcat.embed:tomcat-embed-core:8.5.4
   - org.apache.tomcat.embed:tomcat-embed-core:8.5.6

可以看到在执行gradle build时由于tomcat-embed-core存在版本冲突导致了构建失败,并提示了冲突的两个版本。

依赖报告

Gradle官方提供了一个名叫project-report插件可以让依赖查看更加简单方便,要用此插件只需要在脚本中添加apply plugin: 'project-report’即可。该插件提供的任务可以参考下面的表格,所有输出结果将被放在build/report下。

在这里插入图片描述

使用插件检查更新

使用三方插件进行检查,可以使依赖固定在一个相对新的版本,这里需要注意的是,plugins需要放置在脚本的顶部,更多关于plugins的内容可以查看官方文档

plugins {
    
   id "name.remal.check-dependency-updates" version "1.0.6" 
}

应用此插件后,可以执行gradle checkDependencyUpdates 或 gradle cDU 检查依赖最新版本 : }

> Task :web:checkDependencyUpdates
New dependency version: com.alibaba:druid: 1.0.29 -> 1.1.7
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hai411741962/article/details/133068125

智能推荐

如何配置filezilla服务端和客户端_filezilla server for windows (32bit x86)-程序员宅基地

文章浏览阅读7.8k次,点赞3次,收藏9次。如何配置filezilla服务端和客户端百度‘filezilla server’下载最新版。注意点:下载的版本如果是32位的适用xp和win2003,百度首页的是适用于win7或更高的win系统。32和64内容无异。安装过程也是一样的。一、这里的filezilla包括服务端和客户端。我们先来用filezilla server 架设ftp服务端。看步骤。1选择标准版的就可以了。 _filezilla server for windows (32bit x86)

深度学习图像处理01:图像的本质-程序员宅基地

文章浏览阅读724次,点赞18次,收藏8次。深度学习作为一种强大的机器学习技术,已经成为图像处理领域的核心技术之一。通过模拟人脑处理信息的方式,深度学习能够从图像数据中学习到复杂的模式和特征,从而实现从简单的图像分类到复杂的场景理解等多种功能。要充分发挥深度学习在图像处理中的潜力,我们首先需要理解图像的本质。本文旨在深入探讨深度学习图像处理的基础概念,为初学者铺平通往高级理解的道路。我们将从最基础的问题开始:图像是什么?我们如何通过计算机来理解和处理图像?

数据探索阶段——对样本数据集的结构和规律进行分析_数据分析 规律集-程序员宅基地

文章浏览阅读62次。在收集到初步的样本数据之后,接下来该考虑的问题有:(1)样本数据集的数量和质量是否满足模型构建的要求。(2)是否出现从未设想过的数据状态。(3)是否有明显的规律和趋势。(4)各因素之间有什么样的关联性。解决方案:检验数据集的数据质量、绘制图表、计算某些特征量等,对样本数据集的结构和规律进行分析。从数据质量分析和数据特征分析两个角度出发。_数据分析 规律集

上传计算机桌面文件图标不见,关于桌面上图标都不见了这类问题的解决方法-程序员宅基地

文章浏览阅读8.9k次。关于桌面上图标都不见了这类问题的解决方法1、在桌面空白处右击鼠标-->排列图标-->勾选显示桌面图标。2、如果问题还没解决,那么打开任务管理器(同时按“Ctrl+Alt+Del”即可打开),点击“文件”→“新建任务”,在打开的“创建新任务”对话框中输入“explorer”,单击“确定”按钮后,稍等一下就可以见到桌面图标了。3、问题还没解决,按Windows键+R(或者点开始-->..._上传文件时候怎么找不到桌面图标

LINUX 虚拟网卡tun例子——修改_怎么设置tun的接收缓冲-程序员宅基地

文章浏览阅读1.5k次。参考:http://blog.csdn.net/zahuopuboss/article/details/9259283 #include #include #include #include #include #include #include #include #include #include #include #include _怎么设置tun的接收缓冲

UITextView 评论输入框 高度自适应-程序员宅基地

文章浏览阅读741次。创建一个inputView继承于UIView- (instancetype)initWithFrame:(CGRect)frame{ self = [superinitWithFrame:frame]; if (self) { self.backgroundColor = [UIColorcolorWithRed:0.13gre

随便推点

字符串基础面试题_java字符串相关面试题-程序员宅基地

文章浏览阅读594次。字符串面试题(2022)_java字符串相关面试题

VSCODE 实现远程GUI,显示plt.plot, 设置x11端口转发_vscode远程ssh连接服务器 python 显示plt-程序员宅基地

文章浏览阅读1.4w次,点赞12次,收藏21次。VSCODE 实现远程GUI,显示plt.plot, 设置x11端口转发问题服务器 linux ubuntu16.04本地 windows 10很多小伙伴发现VSCode不能显示figure,只有用自带的jupyter才能勉强个截图、或者转战远程桌面,这对数据分析极为不方便。在命令行键入xeyes(一个显示图像的命令)会failed,而桌面下会出现:但是Xshell能实现X11转发图像,有交互功能,但只能用Xshell输入命令plot,实在不方便。其实VScode有X11转发插件!!方法_vscode远程ssh连接服务器 python 显示plt

element-ui switch开关打开和关闭时的文字设置样式-程序员宅基地

文章浏览阅读3.3k次,点赞2次,收藏2次。element switch开关文字显示element中switch开关把on-text 和 off-text 属性改为 active-text 和 inactive-text 属性.怎么把文字描述显示在开关上?下面就是实现方法: 1 <el-table-column label="状态"> 2 <template slot-scope="scope">..._el-switch 不同状态显示不同字

HttpRequestUtil方法get、post、JsonToPost_httprequestutil.httpget-程序员宅基地

文章浏览阅读785次。java后台发起请求使用的工具类package com.cennavi.utils;import org.apache.http.Header;import org.apache.http.HttpResponse;import org.apache.http.HttpStatus;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpPost;import org.apach_httprequestutil.httpget

App-V轻量级应用程序虚拟化之三客户端测试-程序员宅基地

文章浏览阅读137次。在前两节我们部署了App-V Server并且序列化了相应的软件,现在可谓是万事俱备,只欠东风。在这篇博客里面主要介绍一下如何部署客户端并实现应用程序的虚拟化。在这里先简要的说一下应用虚拟化的工作原理吧!App-V Streaming 就是利用templateServer序列化出一个软件运行的虚拟环境,然后上传到app-v Server上,最后客户..._app-v 客户端