• Gradle 笔记 2


    1 Scope

    [java]
    compileOnly
    runtimeOnly
    implementation
    testCompileOnly
    testRuntimeOnly
    testImplementation
    
    [java-library]
    api
    compileOnlyApi
    
    [war]
    providedCompile
    
    [exclude]
    implementation('org.xx:xx:xx') {
            exclude group: 'org.xx'
            exclude module: 'slf4j-api' // or
            exclude group: 'org.xx', module: 'slf4j-api'
    }
    
    [transitive]
    implementation('org.hibernate:hibernate-core:3.6.3.Final') {
            transitive(false) // no allow transitive
    }
    
    [enfore]
    implementation('org.slf4j:slf4j-api:1.4.0!!')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    2 fast-fail

    configurations.configureEach {
        resolutionStrategy {
            failOnVersionConflict() // fast-fail
            force 'animal:cat:1.0.0' // 强制依赖
        }
    }
    // 同等写法
    configurations.configureEach { Configuration config ->
        config.resolutionStrategy.failOnVersionConflict()
        config.resolutionStrategy.force('animal:cat:1.0.0')
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3 gradle command

    gradle tasks
    gradle build
    gradle run
    gradle tasks --all
    gradle dependencies
    gradle properties
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4 commandline args

    --max-workers --parallel --no-parallel -Dorg.gradle.logging.level=quiet
    -q/quiet -w/warn -i/info -d/debug -x/exclude-task --rerun-tasks # ignore up-to-date
    --continue # generate build report
    
    e.g. gradle init --type pom
    e.g. gradle myTask is equal to gradle mT
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    5 dynamic invoke

    new A().printA()
    // equivalent
    def a = new A()
    invokeVirtual(a, 'printA')
    
    • 1
    • 2
    • 3
    • 4

    6 Domain-Sepcific Languages

    // equivalent to: turn(left).then(right)
    turn left then right
    
    // equivalent to: take(2.pills).of(chloroquinine).after(6.hours)
    take 2.pills of chloroquinine after 6.hours
    
    // equivalent to: paint(wall).with(red, green).and(yellow)
    paint wall with red, green and yellow
    
    // with named parameters too
    // equivalent to: check(that: margarita).tastes(good)
    check that: margarita tastes good
    
    // with closures as parameters
    // equivalent to: given({}).when({}).then({})
    given { } when { } then { }
    
    // equivalent to: select(all).unique().from(names)
    select all unique() from names
    
    // equivalent to: take(3).cookies
    // and also this: take(3).getCookies()
    take 3 cookies
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    7 Delegate & Closure

    Closure closure = {
            sayHello()
    }
    class Foo {
            void sayHello() {
                    println("hello")
            }
    }
    def foo = new Foo()
    closure.delegate = foo
    closure() // invoke
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    equivalent to internal Class

    8 Task

    task A {}
    task(map, 'B')
    tasks.create('C') {}
    tasks.register('D') {} // Lazy loading
    
    // use exist Type
    tasks.register('myClean', Delete) { 
        delete buildDir
    }
    
    task sourcesJar(type: Jar, dependsOn: classes) {
    	classifier = 'sources'
    	from sourceSets.main.allSource
    }
    
    task javadocJar(type: Jar, dependsOn: javadoc) {
    	classifier = 'javadoc'
    	from javadoc.destinationDir
    }
    
    4.times {
            tasks.register("task$it") {
                    doLast {
                            println "I'm task number $it"
                    }
            }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    method: tasks.findByName / getByName / findByPath / getByPath(“:project-a”)
    addRule(“description”) { taskName -> task(taskName) { doLast { print $taskName } } }

    taskName.onlyIf { !project.hasProperty(‘a’) } // return if excute
    defaultTasks ‘taskA’, ‘taskB’ // project default execute Task

    9 Daemon

    jvm start and shutdown is too heavy for system, better than keep running

    gradle connect daemon throught socket

    10 Core Object

    1. Project

    2. Task

    3. Gradle

    4. Gradle 初始化构建, 全局单例

    5. Project pom.xml 模块唯一对应

    6. Settings 项目唯一, 一般只用到 include 方法

    7. Task 前面的有向无环图基于 Task 对象

    11 Life Cycle

    Initialzation
            settings.gradle Gradle#settingsEvaluated
            build.gradle Gradle#projectsLoaded
    Configuration
            allprojects: Gradle#beforeProject and Project#beforeEvaluate
            subprojects: Gradle#beforeProject and Project#beforeEvaluate
            SubProjectA: Gradle#beforeProject and Project#beforeEvaluate
            EXECUTE build.gradle 配置段脚本
            SubProjectA: Gradle#afterProject and Project#afterEvaluate
            ALL READY:
                    Gradle#projectsEvaluated
                    Gradle#taskGraph#whenReady
    Execution
            TaskExecutionGraph#beforeTask
            EXECUTE Task Action
            TaskExecutionGraph#afterTask
            ALL EXECUTED: Gradle#buildFinish
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    12 buildscript

    plugins {
        id 'java'
        id 'org.springframework.boot' version '2.6.3'
        id 'io.spring.dependency-management' version '1.0.15.RELEASE'
    }
    
    group = 'com.xxx.xx'
    version = '1.0-SNAPSHOT'
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter-web'
        testImplementation 'org.springframework.boot:spring-boot-starter-test'
    }
    
    tasks.named('test') {
        // useJUnit() for junit four
        useJUnitPlatform() // for junit jupiter
    }
    
    // or
    buildscript {
        repositories {
            maven { url 'https://maven.aliyun.com/repository/public' }
        }
        dependencies {
            classpath 'org.springframework.boot:spring-boot-gradle-plugin:2.4.1'
        }
    }
    
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    13 buildSrc 目录

    buildSrc 是 Gradle 默认的插件目录, 编译时自动识别代码, 编译成插件

    一般在 gradle init --type pom 之后会生成这个目录

    自定义插件

    buildSrc/src/main/groovy/插件代码
    buildSrc/build.gradle
    
    • 1
    • 2

    14 gradle 中的 dependencyManagement

    参考: https://docs.gradle.org/current/userguide/java_platform_plugin.html


    示例: 如果一个平台声明了org:foo:1.1的约束,并且没有其他东西带来对foo的依赖,foo将不会出现在图中。 但是,如果出现foo,那么通常的冲突解决将开始。如果依赖项引入org:foo:1.0,那么我们将选择org:foo:1.1来满足平台约束。

    1. pom 的创建
    ext {
        // ExtraPropertiesExtension ext is shorthand for project.ext, and is used to define extra properties for the project object.
        // When reading an extra property, the ext. is omitted (e.g. println project.springVersion or println springVersion).
        publishReleaseUrl = 'http://localhost:8...'
        publishSnapshotUrl = 'http://localhost:8...'
        publishUsername = 'admin'
        publishPassword = 'admin123'
    }
    
    plugins {
        id 'java-platform'
        id 'maven-publish'
    }
    
    javaPlatform {
    	// 默认为防止用户错误地引入依赖,而不是引入依赖约束,如果引入依赖会报错失败。
    	// 通过这个配置可以让Gradle允许引入依赖,当然这是可选的
        allowDependencies() // 既定义约束, 也能加入依赖
    }
    
    dependencies {
        constraints { // n. 强制; 束缚
            // 版本号管理 (要统一管理的依赖+版本)
            api 'com.java:java:1.8'
            implementation 'com.google:guava:31.1'
        }
        api platform('com.fasterxml.jackson:jackson-bom:2.9.8')
    }
    
    publishing {
    	publications {
    		myPlatform(MavenPublication) { // MyMavenJava: 发布的任务标识(会出现在面板中)
                // 指定发布成的POM文件 (GAV坐标)
                artifactId = 'poter'
                groupId = 'com.hurry'
                version = '1.0'
    
                from components.javaPlatform
    		}
    	}
    	repositories {  // 有这个才有: publish{yourdefine:myPlatform}PublicationToMavenRepository
    		maven {
                // 私服配置信息
    			if (version.endsWith('-SNAPSHOT')) {
    				url publishSnapshotUrl
    			} else {
    				url publishReleaseUrl
    			}
    			allowInsecureProtocol = true // 是否允许 http
    			credentials {
    				username publishUsername
    				password publishPassword
    			}
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    1. 发布

    在 idea gradle 面板上选择

    Tasks > publishing > publish{yourdefine}PublicationToMavenLocal
    Tasks > publishing > publish{yourdefine}PublicationToMavenRepository

    发布到Maven私服中, 此时我们能看见私服上对应的 pom 上是

    <packaging>pompackaging>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>GAVgroupId>
                ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 使用

    build.gradle

    plugins {
        id 'java-platform'
    }
    dependencies {
        implementation platform('com.hurry:poter-dependencies:1.0')
        implementation 'com.google:guava' // 此时就不用写版本号了
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    项目内

    dependencies {
        // get recommended versions from the platform project
        api platform(project(':platform'))
        // no version required
        api 'commons-httpclient:commons-httpclient'
    	api platform('com.fasterxml.jackson:jackson-bom:2.9.8')
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    15 发包添加源码

    需要插件 java-library 和 maven-publish

    • 获取系统变量 System.getenv(“系统环境变量”)
    • 获取参数: System.getProperty(“-D参数名”)
    plugins {
        id 'java-library'
        id 'maven-publish'
        id 'io.freefair.lombok' version '8.4'
    }
    
    // 注册一个名为 sourcesJar 的 Gradle 任务,使用 Jar 类型
    tasks.register('sourcesJar', Jar) {
        // 任务依赖于 classes 任务(即在执行任务之前会先执行 classes 任务, 因为需要先编译生成后的类文件
        dependsOn classes
        // 设置任务的分类器(classifier)为 'sources'. 使用分类器来区分不同类型的构建输出 (源码、文档、测试报告)
        archiveClassifier = 'sources'
        // sourceSets.main 是 Gradle 中默认的源码集合, 将 sourceSets.main 中的所有源码文件添加到 JAR 文件中
        from sourceSets.main.allSource
        // (二选一) 使用lombok插件
        from sourceSets.main.delombokTask
    }
    
    ext {
    	uname = 'uname'
    	pwd = 'pwd'
    	repoUrl = 'http:///'
    }
    version = '0.0.1-SNAPSHOT'
    
    publishing {
    	publications {
    		privatePublication(MavenPublication) { // 发布的任务标识 (会出现在gradle面板中)
    			from components.java
    			artifact sourcesJar
    		}
    	}
    	repositories {
    		maven {
    			name 'privateRepo'
    			// 私服配置信息
    			url repoUrl
    			allowInsecureProtocol = true
    			credentials {
    				username = uname
    				password = pwd
    			}
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    16 发布到中央仓库

    https://www.jetbrains.com/help/space/publish-artifacts-to-maven-central.html

    17 清除缓存

    针对同一个快照版本的 不同更新, 有时候死活拉不下来, 删除都没用时, 可以试试清除缓存

    在这里插入图片描述

    configurations.all {
        resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
    }
    
    • 1
    • 2
    • 3

    这段代码将 Gradle 的缓存时间设置为0秒,强制每次都从远程仓库下载最新的快照版本

    记录的版本索引都在 maven-metadata.xml 里, 路径为
    ~/.gradle/caches/modules-2/metadata-2.**/descriptors///

    • 清除 Gradle 缓存中所有已下载的依赖项和构建中间文件,从而释放磁盘空间
    gradle cleanBuildCache
    
    • 1
    • 清除指定项目的依赖项缓存,并从远程仓库重新下载依赖项。
    gradle build --refresh-dependencies
    
    • 1

    18 排除指定依赖

    • 单个

    在 Gradle 中,可以使用 “exclude” 块来排除指定的依赖。在需要排除依赖的模块中,添加 “exclude” 块并指定要排除的依赖的组ID和artifact ID。如果需要排除多个依赖,也可以使用通配符来简化配置。例如:

    dependencies {
        implementation('com.example:example-library:1.0') {
        	// 阻止单个依赖
            exclude group: 'org.unwanted', module: 'unwanted-*'
            
            // or 阻止 "com.example:example-library:1.0" 模块所依赖的 所有其他模块 被传递到我们的项目中
            transitive = false
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    ps: 如果发现没有生效, 请排查: 1. 是否有别的依赖项传递了 unwanted 依赖; 2. 是否有别的依赖项传递了 example-library 依赖;

    • 全局排除

    在 Gradle 中,可以使用 “configurations” 块来进行全局依赖排除。在 “configurations” 块中,可以定义一个名为 “all” 的配置,用于在整个项目中排除指定的依赖。例如:

    configurations {
        all {
            exclude group: 'org.unwanted', module: 'unwanted-library'
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    ps: 这种方法可能会影响到整个项目的构建过程,因此应该谨慎使用。如果只需要在特定模块中排除依赖,应该尽量避免在全局配置中进行排除。

  • 相关阅读:
    Java内存模型之JMM
    MySQL高级篇——数据目录
    【Android Gradle 插件】Gradle 扩展属性 ① ( Gradle 扩展属性简介 | Gradle 自定义 task 任务示例 )
    Rust实战系列-Rust介绍
    http和https的区别,以及https涉及到的加密过程
    Mybatis开启日志
    简单三步走搞定动态规划难题,记好这三板斧,动态规划就不难
    Netty学习(二)概述+EventLoop+Channel+ByteBuf
    Python 一网打尽<排序算法>之堆排序算法中的树
    WPF实现轮播图(图片、视屏)
  • 原文地址:https://blog.csdn.net/howeres/article/details/127874606