Gradle

Gradle

Gradle_第1张图片

Gradle 简介

Gradle 是一款Google 推出的基于 JVM、通用灵活的项目构建工具,支持 Maven,JCenter 多种第三方仓库;支持传递性依赖管理、废弃了繁杂的xml 文件,转而使用简洁的支持多种语言(例如:java、groovy 等)的 build 脚本文件

官网地址:

学习Gradle 的原因:

  1. 目前已经有相当一部分公司在逐渐使用Gradle作为项目构建工具了。
  2. 作为Java开发程序员,如果想下载Spring、SpringBoot等Spring家族的源码,基本上基于Gradle构建的。

总之,虽然目前市面上常见的项目构建工具有Ant、Maven、Gradle,主流还是Maven,但是未来趋势Gradle

常见的项目构建工具

Ant: 2000 年 Apache 推出的纯Java 编写构建工具,通过 xml[build.xml]文件管理项目优点:使用灵活,速度快(快于 gradle 和 maven),

缺点:Ant 没有强加任何编码约定的项目目录结构,开发人员需编写繁杂XML 文件构建指令,对开发人员是一个挑战。

Maven: 2004 年Apache 组织推出的再次使用xml 文件[pom.xml]管理项目的构建工具。

优点: 遵循一套约定大于配置的项目目录结构,使用统一的GAV 坐标进行依赖管理,侧重于包管理。缺点:项目构建过程僵化,配置文件编写不够灵活、不方便自定义组件,构建速度慢于 gradle。

Gradle: 2012 年Google 推出的基于Groovy 语言的全新项目构建工具,集合了Ant 和 Maven 各自的优势。

优点:集 Ant 脚本的灵活性+Maven 约定大于配置的项目目录优势,支持多种远程仓库和插件**,侧重于大项目构建**。缺点:学习成本高、资料少、脚本灵活、版本兼容性差等。

劣势:每一个版本都较上一次有非常大的改动,没有做较好向上兼容学习成本高,groovy脚本语言

Whatever:无论哪种项目构建工具,都有自身的优势和劣势,所以选择一款最适合自己的就是最好的。

Gradle是一种开源自动化构建工具,支持多语言环境,受Ant、Maven思想的影响,集二者之大成,相比Ant的不规范,Maven的配置复杂、生命周期限制较多,Gradle既规范也更灵活,可以使用DSL(领域特定语言,如Groovy)编写构建,脚本更加精悍。本课程基于Gradle7讲解。

Gradle_第2张图片

Gradle组成

Gradle_第3张图片

Gradle 安装

Gradle 安装说明

Gradle官网:https://gradle.org/

Gradle官方下载安装教程页面:https://gradle.org/install/

Gradle官方用户手册:https://docs.gradle.org/current/userguide/userguide.html

其中SpringBoot 与Gradle 存在版本兼容问题,Gradle 与Idea 也存在兼容问题,所以考虑到 java 程序员会使用SpringBoot,所以要选择 6.8 版本及高于 6.8 版本的Gradle,那么相应的idea 版本也要升级,不能太老哦。

我们找到我们idea的安装目录,我这里可以看出我要安装7.4的版本。

Gradle_第4张图片

具体参考文档

Gradle_第5张图片

安装JDK

要求Jdk 为 1.8 或者 1.8 版本以上

下载并解压到指定目录

Gradle_第6张图片

我这里下的是完整版本

Gradle_第7张图片

配置环境变量

新建GRADLE_HOME环境变量,变量值为将gradle根目录

Gradle_第8张图片

在path中加入项%GRADLE_HOME%\bin,类似于JDK或Maven的配置

Gradle_第9张图片

打开CMD,执行gradle -v,成功输出版本则表示安装配置完成

Gradle_第10张图片

接着再配置一个GRADLE_USER_HOME环境变量,GRADLE_USER_HOME 相当于配置Gradle 本地仓库位置和 Gradle Wrapper 缓存目录

只能叫GRADLE_USER_HOME,Gradle本地仓库可以和Maven本地仓库目录一致,我这里就选择maven本地的仓库目录了

Gradle_第11张图片

Gradle更换阿里镜像源

Gradle 自带的Maven 源地址是国外的,该Maven 源在国内的访问速度是很慢的,除非使用了特别的手段。一般情况下,我们建议使用国内的第三方开放的Maven 源或企业内部自建Maven 源。

在我们下载的gradle目录下的init.d文件夹下有一个readme.txt的文件

image-20220706095521904

内容如下:

Gradle_第12张图片

所以我们在init.d 文件夹创建init.gradle 文件,内容如下

其中mavenLocal()表示会先使用本地仓库(前提是配置了M2_HOME环境变量),没有的话就执行下面指定仓库的地址查找。

Gradle_第13张图片

allprojects {
    repositories {
        mavenLocal()
        maven { name "AlibabaCentral" ; url "https://maven.aliyun.com/repository/central" } 
        maven { name "AlibabaPublic" ; url "https://maven.aliyun.com/repository/public" } 
        maven { name "AlibabaGoogle" ; url "https://maven.aliyun.com/repository/google" } 
        maven { name "AlibabaGradlePlugin" ; url "https://maven.aliyun.com/repository/gradle-plugin" } 
        maven { name "AlibabaSpring" ; url "https://maven.aliyun.com/repository/spring" } 
        maven { name "AlibabaCentral" ; url "https://maven.aliyun.com/repository/public" } 
        maven { name "Bstek" ; url "https://nexus.bsdn.org/content/groups/public/" } 
        mavenCentral()
    }
    
    buildscript {
        repositories {
             maven { name "AlibabaCentral" ; url "https://maven.aliyun.com/repository/central" } 
             maven { name "AlibabaPublic" ; url "https://maven.aliyun.com/repository/public" } 
             maven { name "AlibabaGoogle" ; url "https://maven.aliyun.com/repository/google" } 
             maven { name "AlibabaGradlePlugin" ; url "https://maven.aliyun.com/repository/gradle-plugin" } 
             maven { name "AlibabaSpring" ; url "https://maven.aliyun.com/repository/spring" } 
             maven { name "AlibabaCentral" ; 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/' }
        }
    }
}

拓展 1:启用init.gradle 文件的方法有:

1.在命令行指定文件,例如:gradle --init-script yourdir/init.gradle -q taskName。你可以多次输入此命令来指定多个init文件

2.把init.gradle文件放到 USER_HOME/.gradle/ 目录下

Gradle_第14张图片

3.把以.gradle结尾的文件放到 USER_HOME/.gradle/init.d/ 目录下

4.以.gradle结尾的文件放到 GRADLE_HOME/init.d/ 目录下

如果存在上面的4种方式的2种以上,gradle会按上面的1-4序号依次执行这些文件,如果给定目录下存在多个init脚本,会按拼音a-z顺序执行这些脚本,每个init脚本都存在一个对应的gradle实例,你在这个文件中调用的所有方法和属性,都会委托给这个gradle实例,每个init脚本都实现了Script接口。

拓展 2:仓库地址说明

mavenLocal(): 指定使用maven本地仓库,而本地仓库在配置maven时settings文件指定的仓库位置。如D:/repository,gradle 查找jar包顺序如下:USER_HOME/.m2/settings.xml >> M2_HOME/conf/settings.xml >> USER_HOME/.m2/repository

maven { url 地址},指定maven仓库,一般用私有仓库地址或其它的第三方库【比如阿里镜像仓库地址】。

mavenCentral():这是Maven的中央仓库,无需配置,直接声明就可以使用。

jcenter():JCenter中央仓库,实际也是是用的maven搭建的,但相比Maven仓库更友好,通过CDN分发,并且支持https访问,在新版本中已经废弃了,替换为了mavenCentral()。

总之, gradle可以通过指定仓库地址为本地maven仓库地址和远程仓库地址相结合的方式,避免每次都会去远程仓库下载依赖库。这种方式也有一定的问题,如果本地maven仓库有这个依赖,就会从直接加载本地依赖,如果本地仓库没有该依赖,那么还是会从远程下载。但是下载的jar不是存储在本地maven仓库中,而是放在自己的缓存目录中,默认在USER_HOME/.gradle/caches目录,当然如果我们配置过GRADLE_USER_HOME环境变量,则会放在GRADLE_USER_HOME/caches目录,那么可不可以将gradle caches指向maven repository。我们说这是不行的,caches下载文件不是按照maven仓库中存放的方式。

拓展 3:阿里云仓库地址请参考:https://developer.aliyun.com/mvn/guide

Gradle_第15张图片

Gradle 项目目录结构

Gradle 项目默认目录结构和Maven 项目的目录结构一致,都是基于约定大于配置【Convention Over Configuration】。其完整项目目录结构如下所示:

Gradle_第16张图片

Tips:

  1. 只有war工程才有webapp目录,对于普通的jar工程并没有webapp目录
  2. gradlew与gradlew.bat执行的是指定wrapper版本中的gradle指令,不是本地安装的gradle指令哦。

Gradle 创建第一个项目

借助于 spring 脚手架创建gradle 第一个项目:https://start.spring.io/

Gradle_第17张图片

项目内容如下:

Gradle_第18张图片

# distributionBase和distributionPath是配合使用,指定gradle解压后的存放位置
# GRADLE_USER_HOME表示用户目录,
	# windows系统:c:\window\\.gradle\
	# linux是$HOME/.gradle
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
# 指定某个版本gradle下载地址,idea插件中规定的版本
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip
# zipStoreBase和zipStorePath配合使用,指定下载gradle.zip存放位置
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

修改gradle的配置项

Gradle_第19张图片

这就是依赖项

Gradle_第20张图片

添加依赖:

Gradle_第21张图片

特别提示 1:使得在Terminal 中执行以gradlew 开头命令和操作图形化的IDEA 使用Gradle 版本不一定是同一个版本

1.Terminal中以gradlew开头指令用的是Wrapper规定的gradle版本,wrapper中规定版本默认和idea插件中规定的版本一致。

2.而图形化的IDEA使用Gradle是本地安装的哦。

特别提示 2:目前只能是在创建项目时重新设置本地gradle,创建新项目需要重新去改。不像maven可以在创建项目之前就可以默认项目配置

特别提示3:当 我 们 在 gradle.build 文 件 添 加 依 赖 之 后 , 这 些 依 赖 会 在 下 载 到GRADLE_USER_HOME/caches/modules-2/files-2.1 目录下面,所以这里的 GRADLE_USER_HOME 相当于 Gradle 的本地仓库,当然也可以如下方式找到jar 包位置。

Gradle_第22张图片

Gradle_第23张图片

Gradle 中的常用指令

常用gradle指令 作用
gradle clean 清空build目录
gradle classes 编译业务代码和配置文件
gradle test 编译测试代码,生成测试报告
gradle build 构建项目
gradle build -x test 跳过测试构建项目

需要注意的是:gradle 的指令要在含有build.gradle 的目录执行

Gradle内置方法

常用的Project方法

方法 描述
afterEvaluate 可以添加一个闭包,它会在项目完成评估后立即执行。当执行属于该项目的构建文件时,会通知此类监听器。
allprojects 配置当前项目以及它的每个子项目
apply 应用零个或多个插件或脚本。
beforeEvaluate 添加一个闭包,它会在项目开始评估前立即执行
configure 通过闭包配置对象集合。
copy 复制指定的文件
defaultTasks 设置此项目的默认任务的名称。当开始构建时没有提供任务名称时使用这些。
delete 删除文件和目录
exec 执行外部命令
file 解析相对于该项目的项目目录的文件路径
findProject 按路径定位项目。如果路径是相对的,则相对于该项目进行解释。
findProperty 找特定属性,如果未找到,则返回给定属性的值或 null
getAllTasks 返回此项目中包含的任务的地图
hasProperty 确定此项目是否具有给定的属性
javaexec 执行 Java 主类
javaexec 执行外部 Java 进程。
mkdir 创建一个目录并返回一个指向它的文件。
property 返回给定属性的值。此方法定位属性如下:
setProperty 设置此项目的属性。此方法在以下位置搜索具有给定名称的属性,并将该属性设置在它找到该属性的第一个位置。
subprojects 配置本项目的子项目
task 创建Task具有给定名称的 a 并将其添加到此项目中
uri 将文件路径解析为 URI,相对于该项目的项目目录

常用方法示例

这是用gradle创建的springboot工程的第一种示例:

这种是在我们idea默认的配置项

plugins {
    //维护springboot的版本号,不单独使用,和下面的俩个插件一起使用
    id 'org.springframework.boot' version '2.7.1'
    //类似于maven中的只做依赖的管理,不做实际依赖
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

group = 'com.zsq'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
    mavenCentral()
}

dependencies {
    //我们前面的插件指定了默认的版本号,做了版本管理,所以我们这可以不用写版本号
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    implementation 'cn.hutool:hutool-all:5.8.4'
}

tasks.named('test') {
    useJUnitPlatform()
}

这是用gradle创建的springboot工程的第二种示例:

buildscript {
    repositories {
        maven { url 'https://maven.aliyun.com/repository/public' }
    }

    dependencies {
        classpath 'org.springframework.boot:spring-boot-gradle-plugin:2.7.1'
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'


group = 'com.zsq'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
    mavenCentral()
}

dependencies {
    //我们前面的插件指定了默认的版本号,做了版本管理,所以我们这可以不用写版本号
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    implementation 'cn.hutool:hutool-all:5.8.4'
}

tasks.named('test') {
    useJUnitPlatform()
}

1.buildscript{}:配置当前gradle脚本自身需要使用的构建信息或依赖
buildscript {
    repositories {
        maven { url 'https://maven.aliyun.com/repository/public' }
    }

    dependencies {
        classpath 'org.springframework.boot:spring-boot-gradle-plugin:2.7.1'
    }
}
2.repositories{}:仓库配置

通过 repositories{} 可以配置maven,ivy,local仓库。这样子,在dependencies{}声明的依赖就可以通过repositories{}中指定的仓库查询到具体的JAR资源。

repositories {
	mavenLocal()
	mavenCentral()
	maven {
		// Name is optional. If not set url property is used
		name = 'Main Maven repository'
		url = 'https://maven.aliyun.com/repository/central'
	}

	//有权限控制的仓库
	maven() {
		credentials {
			username = 'username'
			password = 'password'
		}
		url = 'https://maven.aliyun.com/repository/central'
	}

	//本地仓库
	repositories {
		flatDir(dir: '../lib', name: 'libs directory')
		flatDir {
			dirs '../project-files', '/volumes/shared-libs'
			name = 'All dependency directories'
		}
	}
}
3.dependencies{}:依赖配置

在gradle中dependencies{}是一等公民,它描述了configurations{}中分组依赖的第三方资源。我们可以把依赖简单的分成两大类:

  1. gradle依赖:主要是gradle运行的时候,需要加载一些插件,如android等,此时需要配置它。
  2. 项目编译/运行依赖:编译一个项目,通常需要依赖其他项目或者JAR。
  3. 依赖的常规写法(与maven一致)

下载

//配置依赖
dependencies {
    //compile已过时,推荐使用implementation
	//按照maven名称加载jar
   implementation 'com.google.guava:guava:11.0.2'
    //排除部分依赖
    implementation('org.slf4j:slf4j-simple:1.6.4') {
		exclude 'org.slf4j:slf4j-api'
	}
    //测试模块
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.2'
    
    //依赖其他子项目
    implementation project(':projectA')
	//加载目录下所有的jar
	implementation fileTree(dir: 'libs', include: ['*.jar'])  //多个文件
    
    implementation ('com.google.guava:guava:11.0.2'){
        //在版本冲突的情况下优先使用该版本
        isForce = true
        //禁用依赖传递
        transitive = false
    }
}
//使用dependencis任务可以查看当前依赖树,*表示被忽略的

工程化之插件

获取插件的渠道有以下2种

  • 访问Gradle插件官网
  • Github搜索,有一些插件并没有被官方所收录,但仍然能够使用,但需要承担一些隐藏的风险

现如今使用评率非常高的几款插件:SpringBoot构建插件,Docker容器集成插件,junit单元测试插件等

Gradle 有两种插件

脚本插件script plugins

脚本插件通常是一个脚本,和一个普通的 build.gradle 文件没什么区别 。脚本插件其实并不能算是一个真正的插件,就是一个扩展脚本。但我们不能忽视它的作用,它是脚本模块化的基础。我们可以把复杂的脚本文件,进行分块,分段整理,拆分成一个个职责分明的脚本插件。就像我们平常封装的 Utils 工具类一样,封装一个 utils.gradle 工具脚本。脚本可以存在本地,也可以存在网络上,只需要提供脚本的相对路径或者 URL ,引用方式如下:

//使用本地插件
apply from: './other.gradle'
apply from: this.rootProject.file('other.gradle')

//使用网络远程插件
apply from: 'https://gitee.com/xxx/xx/raw/master/it235.gradle' 
二进制插件binary plugins

我们可以通过二进制插件的ID来应用。插件 ID 是插件的全局唯一标识符或者名字。Gradle中的插件按照来源可以分为核心插件和非核心插件。Gradle 核心插件的特殊之处就在于他们都有一个简短的 ID,例如 Java 插件的是 “java” 。其它非核心二进制插件也必须使用插件ID的完全限定形式(例com.github.foo.bar)。使用二进制插件的方式有2种,如下。

  • 必须结合buildscript{} 应用插件 ,老版本中使用

    //build.gradle中的顶级语句,如下分别是使用java/idea/war/docker插件
    apply plugin: 'java'
    //apply plugin: JavaPlugin 也可以通过指定插件类来应用,与java效果一样
    apply plugin: 'idea'
    apply plugin: "war"
    //声明
    apply plugin: "com.jfrog.bintray"
    apply plugin: 'org.akhikhl.gretty'
    
    //buildscript
    buildscript {
      repositories {
        maven {url "https://maven.aliyun.com/repository/public"}
        maven { url 'https://maven.aliyun.com/repository/jcenter' }
      }
      //应用插件
      dependencies {
        classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.0"
        classpath 'org.akhikhl.gretty:gretty:+'
      }
    }
    
  • plugins{} 新写法,这种叫plugins DSL写法,对应的是PluginDependenciesSpec实例

    //build.gradle中的顶级语句,声明和应用放在一起
    plugins {
        //核心插件,gradle提供
        id 'java'
        id 'eclipse'
        id 'war'
        //非核心插件(社区插件),必须通过id+version的全限定名的方式进行引用
        id 'com.bmuschko.docker-remote-api' version '6.7.0'
        //apply false 表示在父项目中声明,但是父项目不会立即加载,可以在子项目中通过ID的方式进行使用
        id 'com.jfrog.bintray' version '1.8.5' apply false
    }
    //注意:plugins暂时不支持第三方插件,如果要使用第三方插件请使用老的写法。同时plugins中不能随意编写其他的语句体
    
    • apply false的使用场景

      //settings.gradle,有3个子项目
      include 'hello-a'
      include 'hello-b'
      include 'goodbye-c'
      
      //根项目的build.gradle
      plugins {
          //apply false 表示根项目不会解析加载,只进行定义和插件的版本管理
          id 'com.example.hello' version '1.0.0' apply false
          id 'com.example.goodbye' version '1.0.0' apply false
      }
      
      //hello-a/build.gradle
      plugins {
          id 'com.example.hello'
      }
      
      //hello-b/build.gradle
      plugins {
          id 'com.example.hello'
      }
      
      //goodbye-c/build.gradle
      plugins {
          id 'com.example.goodbye'
      }
      
  • 自定义插件

    插件自定义包括三个步骤:建立插件工程、配置参数、发布插件与使用插件。

    插件的源码可以存放在以下3个地方

    • build script中

      可以直接在build.gradle中编写插件,这样的好处是当前项目能够自动编译和加载,但该插件在构建脚本之外不可见。

      class GreetingPlugin implements Plugin<Project> {
          void apply(Project project) {
              project.task('hello') {
                  doLast {
                      println 'Hello from the GreetingPlugin'
                  }
              }
          }
      }
      // Apply the plugin
      apply plugin: GreetingPlugin
      //使用 gradle -q hello 执行即可
      
    • buildSrc project中

      您可以将插件的源代码放在以下目录中(不同语言编写用不同的目录)

      • rootProjectDir/buildSrc/src/main/java
      • rootProjectDir/buildSrc/src/main/groovy
      • rootProjectDir/buildSrc/src/main/kotlin

      Gradle 将负责编译和测试插件,并使其在构建脚本的类路径中可用。该插件对构建使用的每个构建脚本都是可见的。但是,它在构建之外是不可见的,因此您不能在定义它的构建之外重用插件。

    • 独立项目中

      创建一个单独的项目。该项目生成并发布一个 JAR,然后就可以在多个项目中使用该插件,其他开发者也能下载使用。我们一般会在该jar中编写或依赖一些插件,或者将几个相关的任务类捆绑到一起。

你可能感兴趣的:(gradle,gradle,java)