Gradle 6.8

一、Groovy

Groovy是用于Java虚拟机的一种敏捷的动态语言,可以用于面向对象编程,又可以用作纯粹的脚本语言,具有闭包和动态语言中的其他特性。

与Java比较

  • Groovy完全兼容Java的语法
  • 分号是可选的
  • 类、方法默认是pulic的
  • 编译器给属性自动添加了getter/setter方法
  • 属性可以直接使用点号获取
  • 最后一表达式的值会被做为返回值
  • ==等同于equals(),不会有NullPointerExceptions异常

Groovy特性

  • assert语句
  • 可选类型定义
  • 可选括号
  • 字符串表达方式多样
  • 集合API
  • 闭包

实体类定义

  • 分号可省略
  • 类、方法默认是pulic的
  • 编译器给属性自动添加了getter/setter方法
  • 属性可以直接使用点号获取
public class ProjectVersion{
    private int major
    private int minor
    public ProjectVersion(int major,int minor) {
        this.major = major
        this.minor = minor
    }
    public int getMajor(){
        major
    }
    public void setMajor(int major){
        this.major = major
    }
}
ProjectVersion v1 = new ProjectVersion(1,1)
println v1.minor

可选的类型定义

def version = 1

assert

assert version == 2

括号可选

println(version)
// 等同于
println version

字符串

def s1 = 'imooc' // 单引号表示普通字符串
def s2 = "gradle version is ${version}" // 双引号可以引入变量
def s3 = '''my name
 is imooc '''   // 三引号可换行表示

集合api

①list

def buildTools=['ant','maven']
buildTools << 'gradle'
assert buildTools.getClass() == ArrayList
assert buildTools.size() == 3

②map

def buildYears = ['ant':2000, 'maven': 2004]
buildYears.gradle = 2009

println buildYears.gradle
println buildYears['gradle']
assert buildYears.getClass() == LinkedHashMap

闭包

闭包是一个代码块,同方法一样可以有参也可以无参,可以被赋值给一个变量,也可以当作参数传递给一个方法,像普通方法一样调用。

// 闭包1
def c1 = {
    v ->
        println v
}
// 闭包2
def c2 = {
    println 'hello'
}
// 方法1以闭包函数作为参数,调用闭包函数时指定了参数'param'
def method1(Closure closure) {   // Closure不能引入java包
    closure('param')
}
// 方法2以闭包函数作为参数,且直接调用闭包函数
def method2(Closure closure) {
    closure()
}

// 方法调用的是有参闭包函数
method1(c1)
// 方法调用的是无参闭包函数
method2(c2)
// 使用匿名闭包函数
method2 {
    println '闭包'
}
// 使用匿名闭包函数,且函数中调用了其他方法
method2 {
    c2()
}

// 输出得到
param
hello

build.gradle文件解析

plugins {
    id 'java'
}

// 调用Project.class类的void setGroup(Object var1)方法给属性赋值
group 'org.example'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

// void repositories(Closure var1);是以闭包为参数的方法,省略了括号;{mavenCentral()}是匿名闭包函数;
repositories {  
        // 私服
        maven {
            url "http://chenjie.asia/repository/maven-central/"
            credentials {
                username 'admin'
                password 'admin'
            }
        }
        // 本地仓库
        /*
        ①USER_HOME/.m2/settings.xml
        ②M2_HOME/conf/settings.xml
        ③USER_HOME/.m2/repository
         */
        mavenLocal()
        // 中央仓库
        mavenCentral()
}

// void dependencies(Closure var1);是以闭包为参数的方法,省略了括号;{mavenCentral()}是匿名闭包函数;
dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

需要注意顺序,如先加载java插件才能设置sourceCompatibility的值。


二、Gradle

image.png

2.1 项目构建

2.1.1 打包jar项目

image.png

通过Gradle打包成jar,双击Groovy-Tasks-build中的jar即可。如果build.gradle中的插件选择的是java,那么双击build可以达到同样的效果。

> Task :compileJava
> Task :processResources NO-SOURCE
> Task :classes
> Task :jar

可以看到打包经历了四步,最终可以在build/libs文件夹下可以找到jar包。

2.1.2 打包war项目

需要在build.gradle中添加war插件

plugins {
    id 'java'
    id 'war'
}

group 'org.example'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
        // 私服
        maven {
            url "http://chenjie.asia/repository/maven-central/"
            credentials {
                username 'admin'
                password 'admin'
            }
        }
        // 本地仓库
        /*
        ①USER_HOME/.m2/settings.xml
        ②M2_HOME/conf/settings.xml
        ③USER_HOME/.m2/repository
         */
        mavenLocal()
        // 中央仓库
        mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

刷新后会出现war选项

image.png

双击war就会开始打war包

16:04:39: Executing task 'war'...

> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :war

同样在build/libs下可以找到打完的包。

war包的目录结构如下

├── META-INF:存放标签信息
├── WEB-INF:自动生成目录
        └── classes:存放了java字节码文件和resources下的配置文件
        └── lib:存放依赖包
├── index.html

将war包放到tomcat的webapps目录下,启动startup.bat,会自动解压war包并完成部署。

2.2 构建脚本

2.2.1 构建块

Gradle构建中的两个基本概念是项目(project)和任务(task),每个构建至少包含一个项目,项目中包含一个或多个任务。在多项目构建中,一个项目可以依赖于其他项目;类似的,任务可以形成一个依赖关系图来确保他们的执行顺序。

项目(project)

  • group、name、version
  • plugins、dependencies、repositories、task
  • 属性的其他配置方式:ext、gradle.properties

plugins:指定使用的插件
dependencies:声明引入的外部依赖
repositories:依赖的包的仓库
task:声明项目中的任务

任务(task)
任务对应org.gradle.api.Task。主要包括任务动作和任务依赖。任务动作定义了一个最小的工作单元。可以定义依赖于其他任务、动作序列和执行条件。

  • dependsOn
  • doFirst、doLast <<

我们引入的插件中已经集成了项目和任务,如启动jar打包插件时,会按顺序执行如下任务

> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :jar

UP-TO-DATE表示输入没有发生变化,所以跳过当前的步骤。

大多数场景下,我们只需要使用插件即可,只有在插件无法满足需求时,才会需要自己写任务。

2.2.2 自定义任务

在build.gradle中添加自定义任务

def createDir = {
    path ->
        def dir = new File(path)
        if (!dir.exists()) {
            dir.mkdirs()
        }
}
task makeJavaDir() {
    def paths = ['src/main/java', 'src/main/resources', 'src/test/java', 'src/test/resources']
    doFirst {
        paths.forEach(createDir)
    }
}
task makeWebDir() {
    dependsOn 'makeJavaDir'
    def paths = ['src/main/webapp','src/test/webapp']
    doLast{
        paths.forEach(createDir)
    }
}

添加了闭包createDir和自定义任务 makeJavaDir和makeWebDir,且makeWebDir依赖于makeJavaDir 。可以在Tasks-other中找到自定义任务makeJavaDir 和 makeWebDir。


image.png

双击运行makeWebDir后,可以发现先执行了依赖任务makeJavaDir,然后运行了makeWebDir。

2.2.3 构建生命周期

生命周期为: 初始化 -> 配置 -> 执行

配置代码:即在执行代码前执行的,简单理解就是在doFirst和doLast外的代码;
执行代码:简单理解就是在doFirst和doLast中的代码;

image.png

上图是在生命周期的每个阶段执行完成后,都会触发一个钩子程序,我们可以通过重写这个钩子程序来完成更加丰富的功能。

2.3 依赖管理

几乎所有的基于JVM的软件项目都需要依赖外部类库来重用现有的功能。自动化的依赖管理可以明确依赖的版本,可以解决因传递性依赖带来的版本冲突。

工件坐标:即 group、name、version

常用仓库: mavenLocal(本地仓库) / mavenCentral(中央仓库) / jcenter(中央仓库) / 自定义maven仓库(私服)

// 按配置顺序进行查找
repositories {
    // 私服
    maven {
        url "[私服地址]"
    }
    // 本地仓库
    /* 
    ①USER_HOME/.m2/settings.xml 
    ②M2_HOME/conf/settings.xml
    ③USER_HOME/.m2/repository
     */
    mavenLocal()
    // 中央仓库
    mavenCentral()
}

依赖管理: 依赖的传递性,版本冲突和作用域(compile/runtime/implementation/testCompile/testRuntime/testImplementation)

解决版本冲突

  • 查看依赖报告:双击tasks->help->dependencies查看依赖报告
  • 排除传递性依赖
    dependencies {
        compile('org.hibernate:hibernate-core:3.6.3.Final'){
            exclude group:"org.slf4j", module:"slf4j-api"
            //transitive = false  是否传递本身的依赖给宿主程序,默认时true
        }
    }
    
  • 强制指定一个版本
    dependencies {
       configurations.all {
           resolutionStrategy{
               force 'org.slf4j:slf4j-api:1.7.24'
           }
       }
    }
    
  • 修改默认解决策略:
    dependencies {
       configurations.all {
           resolutionStrategy{
               failOnVersionConflict()
           }
       }
    }
    

2.4 多项目构建

settings.gradle文件用于多项目构建时,指定当前项目包含的子项目。

rootProject.name = 'Groovy'
include 'Mode'
include 'Repository'
include 'Web'

2.4.1 依赖其他项目

dependencies {
    // 表示此项目依赖Mode项目
    compile project(":Mode")
}

2.4.2 使用父项目同意子项目的配置

allprojects:包括父项目和子项目
subprojects:只包括子项目,不包括父项目

①所有项目中应用Java插件
在父项目的build.gradle中配置

allprojects {
    apply plugin: 'java'
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
}

②web子项目打包成War
在子项目中配置

plugin {
    id 'java'
}

③所有项目添加logback日志功能
在父项目的build.gradle中配置

allprojects {
    repositories {
        // 私服
        maven {
            url "http://chenjie.asia/repository/maven-central/"
            credentials {
                username 'admin'
                password 'admin'
            }
        }
        // 本地仓库
        /*
        ①USER_HOME/.m2/settings.xml
        ②M2_HOME/conf/settings.xml
        ③USER_HOME/.m2/repository
         */
        mavenLocal()
        // 中央仓库
        mavenCentral()
    }

    dependencies {
        runtime group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.1'
        testCompile group: 'junit', name: 'junit', version: '4.12'
        compile(group: 'org.hibernate', name: 'hibernate-core', version: '3.6.3.Final'){
            exclude group:"org.slf4j", module:"slf4j-api"
        }
    }
}

④统一配置group和version
在父项目下创建文件 gradle.properties,将group和version作为属性写入文件中

group=org.example
version=1.0-SNAPSHOT

2.5 自动化测试

    dependencies {
        testCompile group: 'junit', name: 'junit', version: '4.12'
    }

引入测试框架的依赖,其他同maven没啥区别。测试完成后可以在build->reports->index.html中查看页面报告;或在build->test-results中查看xml格式的测试报告。

测试发现

  • 使用@RunWith
  • 使用@Test
  • 继承junit.framework.TestCase或groovy.util.GroovyTestCase类

2.6 发布

查看官网配置

image.png

可以将包部署到本地或直接发布到中央仓库或私有仓库。

部署到仓库
引入插件

    apply plugin: 'maven-publish'

    publishing {
        publications {
            myPublish(MavenPublication) {
                from components.java
            }
        }
        repositories {
            maven {
                name 'myRepo'
                def releasesRepoUrl = "http://chenjia.asia/repository/maven-releases/"
                def snapshotsRepoUrl = "http://chenjia.asia/repository/maven-snapshots/"
                url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
                credentials {
                    username 'chenjie'
                    password 'chenjie'
                }
            }
        }
    }
image.png
  • publishMyPublishPublicationToMyRepoRepository:就是我们配置的myPublish方法,MyRepo就是配置的仓库,双击这个选项就会将包推送到远程仓库。可以看到远程仓库中已经部署完成。


    image.png
  • publishMyPublishPublicationToMavenLocal:就是将包部署到本地仓库,默认路径是$USER_HOME/.m2/repository。可以看到已经部署到了本地的maven仓库中。

    image.png

  • publishToMavenLocal:将所有包部署到本地

  • publish:将所有包推送到远程仓库

©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,825评论 4 377
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,887评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,425评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,801评论 0 224
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,252评论 3 299
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,089评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,216评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 31,005评论 0 215
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,747评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,883评论 2 255
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,354评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,694评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,406评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,222评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,242评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,017评论 2 281

推荐阅读更多精彩内容

  • 概述 Gradle是新一代构建工具,从0.x版本一路走来虽然国内可寻的资料多了一些,但都是比较碎片化的知识。官方的...
    三也视界阅读 52,013评论 0 38
  • 1. 概述 Pippin, was a Hobbit of the Shire, and one of Frodo...
    孤山之王阅读 987评论 0 7
  • 1. 什么是gradle? 很高兴能向大家介绍Gradle,这是一个基于JVM的富有突破性构建工具。 它为您提供了...
    eSky阅读 634评论 1 0
  • 大家应该都经历过为了学习Hibernate、Spring这样的框架,需要引用大量Jar包而忙得焦头烂额的经历吧。在...
    乐百川阅读 2,168评论 0 16
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,477评论 28 53