Gradle

Gradle

项目结构

|-build # 封装编译后的字节码、打成的包Jar、War,测试报告等信息
|-gradle# 封装包装器文件夹
|	|-wrapper
|		|-gradle-wrapper.jar
|		|-gradle-wrapper.properties
|_src
|	|-main
|	|-test
|-build.gradle 构建脚本
|-gradlew      包装器启动脚本,执行wrapper中gradle的指令
|-gradlew.bat  包装器启动脚本,执行wrapper中gradle的指令
|-settings.gradle 设置文件,定义项目及子项目名称信息,和项目是一一对应关系
  • http://start.spring.io 创建springboot项目

常用指令

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

gradle 的指令要在含有 build.gradle 的目录执行

修改maven下载源

在gradle的init.d目录下创建以.gradle结尾的文件,.gradle文件可以实现在build开始之前执行

allprojects {
    repositories {
        mavenLocal()
        maven {name "Alibaba" ; url "https://maven.aliyun.com/repository/public"}
        maven {name "Bstek" ; url "https://nexus.bsdn.org/content/groups/public/"}
        mavenCentral()
    }

    buildscript {
        repositories {
            maven {name "Alibaba" ; 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/"}
        }
    }
}

启动 init.gradle 文件的方法

  1. 在命令行指定文件;gradle --init-script dir/init.gradle可以多次输入此命令指定多个init文件

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

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

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

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

仓库地址

  • mavenLocal()使用maven本地仓库,本地仓库在配置maven时 settings 文件指定的仓库位置,gradle查找jar包顺序如下:USER_HOME/.m2/setings.xml—>M2_HOME/conf/settings.xml—>仓库地址repositiry
  • maven{url 地址}指定maven仓库
  • mavenCentral()maven中央仓库

本地maven仓库没有依赖,会到配置的仓库远程下载。但是下载的jar不是存储在本地maven仓库,而是放在自己的缓存目录,默认 USER_HOME/.gradle/caches目录,如果配置过 GRADLE_USER_HOME环境变量,则会放在 GRADLE_USER_HOME/caches 目录下

阿里云仓库 https://developer.aliyun.com/mvn/guide

Wrapper 包装器

Gradle Wrapper 是对 Gradle 的一层包装,用于解决实际开发中可能会遇到的不同的项目需要不同版本的Gradle问题

有了 Gradle Wrapper 本地可以不用配置Gradle ,下载Gradle项目后,使用gradle项目自带的wrapper即可

  • 项目中 gradlew、gradlew.bat 脚本用的是wrapper中规定的gradle版本

  • gradle指令用的是本地的gradle,所以gradle指令和gradlew指令所使用的版本有可能不一样,两者使用方式一致,只不过把gradle指令换成gradlew指令

  • 适应gradlew指令时,指定一些参数来控制Wrapper的生成

    • --gradle-version指定使用的gradle版本
      • gradle wrapper --gradle-version=7.4.2升级wrapper版本号,只是修改gradle.properties中的wrapper版本,未实际下载
    • --gradle-distribution-url用于指定下载Gradle发行版的url地址
  • GradleWrapper执行流程

    • 第一次执行 ./gradle build 命令时,gradle会读取 gradle-wrapper.properties文件的配置信息
    • 准确的将指定版本的 gradle 下载并解压到指定的位置GRADLE_USER_HOME 目录下的wrapper/dists目录中
    • 并构建本地缓存GRADLE_USER_HOME目录下caches目录中,下次再使用相同版本的gradle就不用下载了
    • 之后执行的 ./gradlew 所使用命令都是使用的指定的gradle版本
  • gradle-wrapper.properties 文件

    • # 下载的gradle压缩包解压后存储的 主目录
      distributionBase=GRADLE_USER_HOME
      #相对于distributionBase的解压后的gradle压缩包的路径
      distributionPath=wrapper/dists
      distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip
      # 下载的gradle的压缩包的 存储主目录
      zipStoreBase=GRADLE_USER_HOME
      # 压缩包相对 zipStoreBase 的存储路径
      zipStorePath=wrapper/dists
      

GRADLE_USER_HOME 环境变量用于 gradle wrapper 下载的特定版本的 gradle 存储目录,如果没有配置过 GRADLE_USER_HOME 环境变量 ,默认在当前用户家目录下的 ./gradle文件夹中

Gretty 部署项目

  • 支持 tomcat、jetty 等 Servlet 容器

  • 支持项目热部署、HTTPS、调试

  • 引入插件

    plugins{
    	id 'war'
    	id 'org.gretty' version '2.2.0'
    }
    //Gretty插件配置
    gretty{
        httpPort=8080
        contextPath='/web'
        debugPort=5005//default
        debugSuspend=true//default
        managedClassReload=true//修改类之后重新加载
        servletContainer='tomcat8'//默认使用的是jetty9服务器,支持tomcat7/8
        httpsEnabled=true //支持https
        httpsPort=4431
    }
    
  • 执行Gretty插件 gradle appRun

  • 官方文档:http://akhikhl.github.io/gretty-doc/Gretty-configuration.html

对测试的支持

测试任务自动检查并执行测试源集中的所有单元测试,测试执行后会生成一个报告,支持JUNIT 和 TestNG 测试

测试报告在 build/reports 目录下

  • 对Junit5.x版本支持

    dependencies {
        testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
        testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
    }
    
    test {
        enabled=true//执行测试,false构建跳过测试
        useJUnitPlatform()//支持Junit5
        include 'com/aa/**'    // 只执行com/aa 下的测试
        exclude 'com/aa/bb/**' //排除com/aa/bb 下的测试
    }
    

    在 build.gradle 目录下执行 gradle test指令,gradle就会执行所有加了@Test注解的测试,并生成测试报告

Gradle 项目生命周期

Initialization–>configuration–>execution

  • Initialization 初始化项目构建
    • 执行 GRADLE_USER_HOME/init.gradle init script 初始化操作,如配置仓库、用户名、密码等
    • 执行 settings.gradle 初始化一次构建所参与的所有模块
  • configuration 加载项目中所有模块的Build Script,根据脚本创建对应的task,最终根据所有task生成 Task 组成的有向无环图
    • 执行 build.gradle ,先加载根目录下的构建脚本,在加载子目录下的构建脚本
  • execution 根据上阶段构建的有向无环图,按顺序执行

settings 文件

在项目初始化阶段确定一下引入哪些工程,需要加入到项目构建中,为构建项目工程树做准备

  • 内容:主要定义了当前gradle 项目及子project的项目名称
  • 位置:必须在根目录下
  • 文件名:settings.gradle
  • 对应实例:org.gradle.api.initialization.Settings 实例,每个项目只有一个settings文件
  • 只需要关注文件中的 include方法,使用相对路径引入工程,:代表项目分割符,如果以:开头,则表示相对于 rootProject
//根目录项目名
rootProject.name = 'Gradle_Demo'

//包含子工程名称
include 'project1'
//包含的子工程下的工程名称
include 'project1:subproject1'

Task

项目实质上是Task对象的集合,一个Task表示一个逻辑上较为独立的执行过程,比如编译Java源代码,拷贝文件,打包Jar文件,甚至可以是执行一个系统命令,另外一个Task 可以读取和设置Project的Property已完成特定的操作

文档:https://docs.gradle.org/current/userguide/tutorial_using_tasks.html

task task1 {
//    任务配置段:配置阶段执行
    println '配置任务 task1'
//    任务行为:执行阶段执行,doFirst 会在 doLast 执行之前执行
    doFirst {
        println 'dofirst'
    }
    doLast {
        println('dolast')
    }
}

根目录下执行gradlew task1

  • 无论是定义任务自身的action还是添加的doFirst、doLast方法,其实底层都被放入到一个Action的List中,最初这个action List 是空的,当我们设置了action任务自身的行为,它先将action添加到列表中,此时列表中只有一个action,后续执行doFirst的时候doFirst在action前面添加,执行doLast的时候doLast在action后面添加(有多个doFirst、doLast时,最后添加的doFirst在最前面,最后的doLast在最后面),最后这个List形成doFirst、doSelf、doLast 的执行顺序

任务的依赖关系

dependsOn

  • 参数依赖
task a{
    doLast {
        println('Task a')
    }
}

task b{
    doLast {
        println('Task b')
    }
}
// 参数方式依赖, dependsOn 后面用 :
task c(dependsOn:['a','b']){
    doLast {
        println('Task c')
    }
}

  • 内部依赖
 task a{
     doLast {
         println('Task a')
     }
 }
 
 task b{
     doLast {
         println('Task b')
     }
 }
 
 task c{
 	dependsOn=['a','b']
     doLast {
         println('Task c')
     }
 }
  • 外部依赖
task a{
    doLast {
        println('Task a')
    }
}

task b{
    doLast {
        println('Task b')
    }
}

task c{
	
    doLast {
        println('Task c')
    }
}
c.dependsOn=['a','b']
  • task可以跨项目依赖
  • 一个task依赖多个task时,被依赖的task之间如果没有依赖关系,那么它们的执行顺序是随机的
  • 重复依赖的任务只会执行一次

任务定义方式

  • 通过Project 中的 task() 方法

    //方式一
    task ('A',{
    	println 'A'
    })
    
    //方式二
    task ('B'){
    	println 'B'
    }
    
    //方式三
    task C{
    	println 'C'
    }
    //方式四
    def map = new HashMap();
    map.put("action",{println 'D'})
    task(map,'D')
    
  • 通过 tasks 对象的 create 或者 register 方法

    tasks.create('E'){
    	println 'E'
    }
    
    //regists 执行的是延迟创建,只有当task被需要使用的时候才会被创建
    tasks.register('F'){
    	println 'F'
    }
    

定义任务的同时指定任务的属性,也可以给已有的任务动态分配属性

配置项 描述 默认值
type 基于一个存在的Task来创建,和类继承相似 DefaultTask
overwrite 是否替换存在的Task,与type配合使用 false
dependsOn 配置任务的依赖 []
action 添加到任务中的一个Action或者闭包 null
description 配置任务的描述 null
group 用于配置任务的分组 null
task(group: 'atguign',description: '这是任务A','A')

task H{
    group('atguign')
    description '这是任务H'
}

task F{}
F.group="atguign"


clean.group('atguign')//给已有的clean任务重新指定组信息

任务类型

常见任务类型 任务作用
Delete 删除文件或目录
Copy 将文件复制到目标目录中,可以在复制时重命名和筛选文件
CreateStartScripts 创建启动脚本
Exec 执行命令进程
GenerateMavenPom 生成Maven模块描述符POM文件
Jar 组装Jar文件
War 组装War文件
JavaCompile 编译Java源文件
Javadoc 为Java类生成HTMLAPI文档
Test 执行JUnit或者TestNG测试
PublishToMavenRepository 将MavenPublication发布到mavenartifactrepostal
Upload 将Configuration的构建上传到一组存储库
GradleBuild 执行Gradle构建
Tar 组装Tar存档文件
Zip 组装ZIP归档文件,默认是压缩ZIP的内容
task A(type:Delete){
    // Delete 的两个属性
    delete 'file'//删除file文件
    followSymlinks(true)
}
  • 自定义Task类型

    class CustomTask extends DefaultTask{
        //@TaskAction 表示Task本身要执行的方法
        @TaskAction
        def doSelf(){
            println 'Task 自身在执行的 in doSelf'
        }
    }
    def myTask = task MyTask(type:CustomTask)
    
    myTask.doFirst {
        println('task doFirst')
    }
    
    myTask.doLast {
        println('task doLast')
    }
    
    //执行 gradlew MyTask 输出
    //task doFirst
    //Task 自身在执行的 in doSelf
    //task doLast
    

任务执行顺序

三种方式指定 Task 执行顺序

  • dependsOn强依赖方式
  • 通过 Task 输入输出
  • 通过 API 指定执行顺序

https://docs.gradle.org/current/dsl/org.gradle.api.Task.html

动态分配任务

一旦注册了任务,就可以通过API访问它们

//注册四个任务
4.times {counter->
    tasks.register("task$counter"){
        doLast{
            println("$counter")
        }
    }
}
//通过api访问任务0;任务0 强依赖任务2、任务3
//构建4个任务,任务2、任务3 需要在 任务0 之前优先加载
tasks.named('task0'){
    dependsOn('task2','task3')
}

任务的关闭与开启

每个任务都有一个 enabled默认是true,将其设置为 false 阻止执行任何任务动作,禁用的任务将标记为“跳过”

task a{
    doLast {
        println('a')
    }
    enabled(true)//显示设置任务开启,默认是true
}

a.enabled=false//设置任务关闭

任务超时

每个任务都有一个 timeout 可用于限制执行的时间属性,当任务达到超时时,其任务执行线程将被中断,该任务将被标记为失败,终结器任务仍将运行。如果 --continue 使用,其他任务可以在此之后继续执行。不响应中断的任务无法超时。Gradle 的所有内置任务均会及时响应超时

task A{
    doLast {
        Thread.sleep(1000)
        println('任务A')
    }
    //500毫米超时
    timeout= Duration.ofMillis(500)
}

task B{
    doLast {
        println('任务B')
    }
}
// 执行 gradlew A B  A超时,抛出异常,B没有执行
// 执行 gradlew A B --continue A抛出异常,B继续执行

任务查找

task A{
    doFirst {
        println('doFirst 1')
    }

}
//根据任务名查找,只能找当前文件中的任务,不可跨项目
tasks.findByName('A').doFirst {println('doFirst 2')}
tasks.findByName('A').doFirst {println('doFirst 3')}
//根据任务相对路径查找,可以跨项目 :表示相对于根目录
tasks.findByPath(':A').doFirst {println('doFirst 4')}
//输出 4 3 2 1

任务规则

执行、依赖一个不存在的任务时,gradle 会执行失败,报错误信息,改进成不报错,打印提示信息

task Hello{
    doLast {
        println('Hello')
    }
}

tasks.addRule("规则描述,方便调试"){
    String taskName->task(taskName){
        doLast {
            println("该 $taskName 任务不存在!!!")
        }
    }
}

// gradlew aaa Hello  
// aaa 不存在也不会报错,Hello 任务照常执行

任务 onlyIf 断言

Task 有一个 onlyIf 方法,接收一个闭包作为参数,如果该闭包返回true则该任务执行,否则跳过

控制哪些情况打什么包,什么时候执行单元测试等

task Hello{
    doLast {
        println('Hello')
    }
}

// 通过 -P 为Project 添加 指定属性
// gradlew Hello -P aaa
Hello.onlyIf {!project.hasProperty('aaa')}

默认任务

gradle 允许定义一个或者多个在没有指定其他任务时执行的默认任务

// 声明为默认任务,只要执行grade命令,默认任务就会执行
defaultTasks('Hello','World')
tasks.register('Hello'){
    doLast{
        println('Default Hello')
    }
}

tasks.register('World'){
    doLast{
        println('Default World')
    }
}


tasks.register('other'){
    doLast{
        println('other')
    }
}

文件操作

本地文件

使用 Project.file(java.lang.Object) 方法,创建的 File 对象就是Java中的File对象。通过指定文件相对路径或绝对路径来对文件操作,相对路径为相对当前project的目录

//使用相对路径
File configFile = file('src/conf.xml')
configFile.createNewFile()

//使用绝对路径
configFile = file('D:\\conf.xml')
configFile.createNewFile()

//使用一个文件对象
configFile = new File('src/config.xml')
configFile.createNewFile()

文件集合

文件集合就是一组文件的列表,we年集合用 FileCollection 接口表示,可以使用 Project.files(java.lang.Object) 方法来获取一个文件集合对象

def collection = files('src/a.xml', new File('src/b.xml'), 'src/c.xml')

collection.forEach() {
    it.createNewFile()
    println it.name
}
// 文件结合转成Set类型
Set set1 = collection.files
Set set2 = collection as Set

//文件集合转List
List list = collection as List

for (item in list) {
    println(item.name)
}
// 添加 或者 删除 一个集合
def union = collection + files('src/d.xml')
union.forEach(){
    println(it.name)
}
def minus = collection - files('src/d.xml')
minus.forEach({println(it.name)})

文件树

文件数是有层级结构的文件集合,一个文件树可以代表一个目录结构或者ZIP压缩包中的内容结构。

文件树是从文件集合继承过来的,文件树具有文件集合的所有功能

//使用路径创建问价树对象,同时指定包含的文件
ConfigurableFileTree tree = fileTree('src/mian').include('**/*.java')

tree.forEach({println(it.name)})

文件拷贝

使用Copy任务来拷贝文件。可以过滤指定拷贝内容,能对文件进行重命名操作等。Copy任务必须指定一组需要拷贝的文件和拷贝的目录

task Hello(type : Copy){
//    CopySpec.from(java.lang.Object) 指定原文件
//    参数不存在,会被忽略
//    参数是目录时,拷贝目录下所有文件,目录本身不会被拷贝
    from 'src'
//    参数是文件时,拷贝文件到指定目录
    from 'gradle/wrapper/gradle-wrapper.properties'
//    参数是ZIP压缩文件,该压缩文件中内容会被拷贝到指定目录,解压缩
    from 'a/a.zip'


//    CopySpec.into(java.lang.Object)  指定目标目录
    into 'src/main/'
//   拷贝符合条件的文件
    include('*.xml')
//    排除其中某些文件
    exclude('c.*')

//    拷贝时重命名文件
    rename {String name->
        name.replace('xml','yaml')
    }

}

直接使用 Project.copy(org.gradle.api.Action) 方法

copy {
    from('src/a.xml')
    into('src/main/')
}
// 执行 gradlew build 即可

归档文件

项目打包成 war、Jar、Zip、Tar 包,使用 Zip、Tar、Jar、War、Ear 任务来实现

apply(plugin:'java')
version('1.0')
task myJar(type:Jar){
    from('src/mian')
    into('build')
//指定打包后的包名
    baseName('demo')
}
//打印包名
println(myJar.archiveName)

依赖

/**
 * 依赖方式:
 *      本地依赖:依赖本地的某个jar包,可通过 文件集合、文件树的方式指定
 *      项目依赖:依赖某个project
 *      直接依赖:依赖的类型 依赖的组名:依赖的名称:依赖的版本号
 *
 * 依赖下载:
 *      当执行 build 命令时,gradle会去配置的依赖仓库中下载对应的Jar
 */
dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'

//    直接依赖
    implementation 'org.apache.logging.log4j:log4j-spring-cloud-config-client:2.17.2'
    implementation group: 'org.apache.logging.log4j', name: 'log4j-spring-cloud-config-client', version: '2.17.2'

//    本地依赖,通过文件集合
    implementation files('lib/mysql.jar')
//    本地依赖,通过文件树
    implementation fileTree('dir': 'lib', includes: ['*.jar'], excludes: ['mysql.jar'])
//    项目依赖,被依赖的文件名一定要在settings.gradle文件中存在
    implementation project(':webproject')
}
依赖的类型 说明
compileOnly 由java插件提供,适用于编译期需要而不需要打包的情况
runtimeOnly 由java插件提供,运行期需要,编译期不需要的情况
implementation 由java插件提供,针对源码"src/main"目录,在编译、运行时都有效
testCompileOnly 由java插件提供,只在测试编译期需要,而测试运行不需要
testRuntimeOnly 由java插件提供,只在测试运行时需要,而测试编译期不需要
testImplementation 由java插件提供,针对源码"src/test"目录,在测试编译、运行时都有效
providedCompile 由War插件提供,编译测试阶段代码需要依赖此jar包,而运行阶段容器已经提供了相应的支持,所以无需将这些文件打入war包中
api 由java-library插件提供,这些依赖项可以传递性地导出给使用者,用于编译时和运行时
compileOnlyApi 由java-library插件提供,声明模块和使用者在编译时需要的依赖项,但在运行时不需要
  • java插件提供的功能,java-library插件都提供

api 与 implementation 区别

api implementation
编译时 能进行依赖传递,底层变,全部都要变、编译速度慢 不能进行依赖传递,底层变,不用全部都要变,编译速度快
运行时 运行时会加载,所有模块的class都要被加载 运行时会加载,所有模块的class都要被加载
适用于多模块依赖,避免重复依赖模块 多数情况下使用implementation

依赖冲突解决

		  B-->log4j 1.4.2
		 /
		/
ProjectA
		\
		 \
		  C-->log4j 2.2.4

A、B、C都是本地项目module,log4j 是远程依赖

编译时:B用1.4.2,C用2.2.4,B和C之间没有冲突

打包时:只有一个版本的代码打包进入最终的A对应的包中,这里就有冲突了

  • 依赖冲突时,默认情况下,gradle 会使用其中最新版的 jar 包
  • 使用exclude移除一个依赖,不允许依赖传递,强制使用某个版本
//移除依赖
dependencies {
implementation('org.heibernate:hibernate-core:3.6.1.Final'){
//    排除某个库(slf4j)依赖,三种写法
    exclude(group:'org.slf4j')
    exclude(module:'slf4j-api')
    exclude(group:'org.slf4j',module:'slf4j-api')
}
//    排除后,使用手动引入
    implementation('org.slf4j:slf4j-api:1.4.0')
}

//不允许依赖传递
dependencies {
    implementation('org.heibernate:hibernate-core:3.6.1.Final') {
//    不允许依赖传递,一般不用
        transitive(false)
    }
//    排除后,使用手动引入
    implementation('org.slf4j:slf4j-api:1.4.0')
}

//强制使用
dependencies {
    implementation('org.heibernate:hibernate-core:3.6.1.Final') 
//    !! 强制使用1.4.0版本
    implementation('org.slf4j:slf4j-api:1.4.0!!')
}

dependencies {
    implementation('org.heibernate:hibernate-core:3.6.1.Final')
//    强制使用1.4.0版本
    implementation('org.slf4j:slf4j-api:1.4.0'){
        version({strictly('1.4.0')})
    }
}

dependencies {
    implementation('org.heibernate:hibernate-core:3.6.1.Final')
//    +/latest.integration 动态版本声明,使用中心仓库中最新版本,不建议用
    implementation('org.slf4j:slf4j-api:+')
    //implementation('org.slf4j:slf4j-api:latest.integration')
}
//当遇到版本冲突,立即构建失败
configurations.all() { Configuration configuration ->
    configuration.resolutionStrategy.failOnVersionConflict()
}

插件

  • 可以添加任务到项目中,从而帮助完成测试、编译、打包等
  • 可以添加依赖配置到项目中
  • 可以向项目中拓展新的属性、方法等
  • 可以对项目进行一些约定,如应用java插件后,约定src/main/java目录是源代码的位置,编译时编译这个目录下的java源代码

脚本插件

本质就是一个脚本文件,使用时通过 apply from: 将脚本加载进来,脚本可以是本地文件也可以是网络上的文件

//vsersion.gradle文件
//ext 拓展
ext{
//  key=value
    company='脚本'
    //key=Map
    cfgs=[jdk:'11']

    spring=[version:'2.2.0']
}
//build.gradle 文件
//'version.gradle' 可以是本地地址,也可以是网络地址
apply from:'version.gradle'

task Hello{
    doLast {
        println("company $company JDK版本:$cfgs.jdk  spring版本$spring.version")
    }
}

对象插件

对象插件就是实现了 org.gradle.api.Plugin 接口的插件,每个插件都有一个 plugin id

gradle内部插件使用
/**
 * apply(map具名参数方式)
 * key:plugin
 * value: 插件id/插件的全类名/插件的简类名
 */
apply plugin:'java'
//apply plugin:'JavaPlugin'
//apply plugin:'org.gradle.api.plugins.JavaPlugin'


apply{
	plugin 'java'
}
第三方插件
  • 使用第三方插件,一般需要配置对应的仓库和类路径
//这个要放在最前面
buildscript {
    ext{
        springBootVersion='2.3.3.RELEASE'
    }
    //配置仓库
    repositories {
        mavenLocal()
        maven {url 'http://maven.aliyun.com/nexus/content/groups/public'}
    }
    //引入插件
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

//应用插件
//社区插件,需要事先引入,不必写版本号
apply {plugin:'org.springframework.boot'}
  • 如果第三方插件已经托管在 https://plugins.gradle.org 网站上,可以直接使用
plugins{
    id 'org.springframework.boot' version '2.4.1'
}
用户自定义插件
  • 只能在当前project中使用
class GreetingPlugin implements Plugin{
    void apply(Project project){
        project.task('hello'){
            doLast {
                println('Hello from the GreetingPlugin')
            }
        }
    }
}

apply plugin:GreetingPlugin
  • 在其他项目中使用

buildSrc 是Gradle 默认的插件目录,编译Gradle的时候会自动识别这个目录,将其中代码编译为插件

首先建立一个buildSrc 的javaModule,将 buildSrc 从 included 从 included modules 移除,重新构建,然后只保留 build.gradle 和 src/mian 目录,其他全部删除掉,注意名字一定是 buildSrc ,不然会找不到插件

修改 build.gradle 中的内容

apply plugin:'groovy'//必须 
apply plugin:'maven-publish'

dependencies {
    implementation(gradleApi())//必须
    implementation(localGroovy())//必须
}

repositories {
    google()
    mavenCentral()//必须
}

//项目入口设置为 src/main/groovy
sourceSets{
    main{
        groovy{
            srcDir 'src/main/groovy'
        }
    }
}

创建入口目录,在 src/main 下创建代码入口目录

|--buildSrc
	|--src
		|--main
			|--groovy
				|--com
					|--xxx
						|--Test
			|--resources
				|--META-INF
					|--gradle-plugins
						|--*.properties任何以.properties结尾的文件

实现插件代码 Test.groovy

package com.xxx

import org.gradle.api.Plugin
import org.gradle.api.Project

class Test implements Plugin{
    @Override
    void apply(Project project){
        project.task('hello'){
            doLast {
                println('自定义 Plugin')
            }
        }
    }
}

在 *.properties 文件中指出实现插件的全类名

implementation-class=com.xxx.Test

使用,在module引入写的插件 apply plugin:‘.properties文件的文件名’

  • 插件上传maven仓库

将上面写好的插件, buildSrc 文件夹复制一份,修改名称,并把复制的这个 include 到根项目下settings.gradle 中

修改build.gradle文件

apply plugin: 'groovy'//必须
apply plugin: 'maven-publish'

dependencies {
    implementation(gradleApi())//必须
    implementation(localGroovy())//必须
}

repositories {
    google()
    mavenCentral()//必须
}

//项目入口设置为 src/main/groovy
sourceSets {
    main {
        groovy {
            srcDir 'src/main/groovy'
        }
    }
}


publishing {
    publications {
    //myLibrary 组件名称,随便写
        myLibrary(MavenPublication) {
            //指定GAV坐标信息
            groupId = 'com.xxx.plugin'
            version = '1.0'
            from components.java//发布jar包
//            from components.web//引入war插件,发布war包
        }
    }
    repositories {
        //当前项目目录下
        maven { url "$rootDir/lib/release" }

        //
        maven {
//            name 属性可选,表示仓库名称 url 必填
            name = 'myRepo'
//            本地maven
            url = layout.buildDirectory.dir("repo")
//            发布到maven私服
//            url = 'http://xxxx'
//            认证信息:用户名和密码
//            credentials {
//                username = ""
//                password = ""
//            }
        }
    }
}

找到对应模块的publishing,点击 publish 发布

按照第三方插件使用方式使用

插件的分析使用

  • 插件的引入
  • 主要的功能(任务)gradlew tasks查看加入某个插件前后的区别
  • 工程目录结构;有的插件对目录结构有约束,可以通过属性修改
  • 依赖管理方式;不同插件提供不同的依赖管理
  • 插件的常用属性

build.gradle文件

  • gradle 的构建脚本文件

  • 每个project都会有一个 build.gradle 文件,该文件是项目构建的入口,可配置版本、插件、依赖库等

  • 每个build文件都有一个对应的 Project 实例,对 build.gradle 文件配置,本质是设置 Project 实例的属性和方法

  • 在 root project 中可以获取到所有的 child project ,可以对 child project 统一配置

  • build中常用属性/方法

    • plugins{
          id 'java'
          id 'maven-publish'
      }
      
      rootProject.name='demo'    项目名称,在settings.gradle 文件中
      
      group 'com.xxx'   项目分组
      version '1.0' 项目版本
      sourceCompatibility=11   源码JDK版本
      targetCompatibility=11   生成class文件的JDK版本
      compileJava.options.encoding='UTF-8'  源码解码字符集
      compileTestJava.options.encoding='UTF-8' 测试解码字符集
      //编译java文件时采用utf-8,源码的编码字符集
      tasks.withType(JavaCompile){
          options.encoding('UTF-8')
      }
      tasks.withType(Javadoc){
          options.encoding('UTF-8')
      }
      
      
      
      
      
      buildscript {} 获取依赖插件
      apply() 应用插件
      task() 定义任务
      plugins{} 应用插件
      dependencies {}设置项目依赖
      repositories {}设置项目仓库
      allprojects {} 设置所有project信息
      subprojects {}设置子模块的信息
      sourceSets {}设置项目的源代码文件集合
      publishing{}配置发布插件
      configurations {}配置此项目的依赖项配置
      artifacts {} 配置此项目的已发布构件
      
      //对单个project进行配置
      project('project名称、路径'){}
      
      ext{}//添加自定义属性
      
  • ext配置用户自定义属性,而gradle.properties中一般定义 系统属性、环境变量、项目属性、JVM相关配置信息,该文件中的属性会自动在项目运行时加载

    #设置此参数主要是编译下载包会占用大量的内存,可能会内存溢出
    org.gradle.jvmargs=-Xms4096m -Xmx8182m
    #开启gradle缓存
    org.gradle.caching=true
    #开启并行编译
    org.gradle.parallel=true
    #启用新的孵化模式
    org.gradle.configureondemand=true
    #开启守护进程
    org.gradle.daemon=true
    
    

项目发布

plugins{
    id 'maven-publish'//必须插件,maven发布插件
    id 'java-library'//带源码和Javadoc发布
}
javadoc.options.encoding='UTF-8'
java{
    //生成文档包
    withJavadocJar()
//    生成源码包
    withSourcesJar()
}

publishing {
    publications{
        demoProject(MavenPublication){
//            指定GAV坐标信息
            groupId='com.aaaa.xxx'
            artifactId='xxxx'
            version='1.0'
            //发布jar包
            from components.java
        }
    }
    repositories {
//        本地仓库位于USER_HOME/.m2/repository
        mavenLocal()
//        发布项目到私服
        maven {
//            发布地址可以是本地仓库或者私服
//            url = layout.buildDirectory.dir('repo')
//            url='http://xxxx.xxx'
            credentials{
                username=''
                password=''
            }
        }
    }
}

生命周期

  • 钩子函数
// 1 初始化阶段 settingsEvaluated
gradle.settingsEvaluated {
    println('1、初始化阶段')
}
// 2 初始化阶段 projectsLoaded
gradle.projectsLoaded {
    println('2、初始化阶段')
}

def projectName = ''
gradle.addProjectEvaluationListener(new ProjectEvaluationListener() {
//    3.执行各个 project 的 beforeEvaluate :在配置阶段完成
    @Override
    void beforeEvaluate(Project project) {
        projectName = project.named
        println("3 $projectName beforeEvaluate")
    }
//    5.执行各个 project 的 afterEvaluate :在配置阶段完成
    @Override
    void afterEvaluate(Project project, ProjectState projectState) {
        println("5 $project.name afterEvaluate")
    }
})
//4.执行各个 project 的 beforeProject :在配置阶段完成
gradle.beforeProject {
    println("4 $projectName beforeProject")
}
//6 执行各个 project 的 afterProject :在配置阶段完成
gradle.afterProject {
    println("6 $projectName afterProject")
}
// 7 所有工程的 build.gradle 执行完毕后,回调 Gradle 对象的 projectsEvaluated 方法:在配置阶段完成
def rootProjectName = rootProject.getName()
gradle.projectsEvaluated {
    println("7 $rootProjectName projectsEvaluated")
}
//8 配置阶段完毕后 回调 TaskExecutionGraph 对象的 whenReady 方法:在配置阶段完成
gradle.taskGraph.whenReady {
    println("8 $rootProjectName taskGraph.whenReady")
}

//9 在当前 Task 执行前,会回调 TaskExecutionGraph 对象的  beforeTask 方法:在执行阶段完成
gradle.taskGraph.beforeTask {
    task->
        println("$task.name  $task.getProject().name")
}

//10 在当前 Task 执行后,会回调 TaskExecutionGraph 对象的  afterTask 方法:在执行阶段完成
gradle.taskGraph.afterTask {
    task->
        println("$task.name  $task.getProject().name")
}

//11 当所有 Task 执行完毕后,会回调 Gradle 对象的 buildFinished:在执行阶段完成
gradle.buildFinished {
        println("$rootProjectName")
}

创建SpringBoot项目

  • build.gradle

    plugins{
        id 'org.springframework.boot' version '2.3.7.RELEASE'//用以维护springboot版本号
        id 'io.spring.dependency-management' version '1.0.10.RELEASE'//只做依赖的管理,不做实际依赖
    //上面两个一起使用
        id 'java'
    }
    
    group 'com.xxx'
    version '1.0'
    
    repositories {
        mavenLocal()
    }
    
    dependencies {
        implementation('org.springframework.boot:spring-boot-starter-web ')
    }
    
    • 如果要管理 org.springframework.boot 和 io.spring.dependency-management 的版本则要用 spring-boot-gradle-plugin 插件

      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'
      apply plugin:'java'
      
      
      group 'com.xxx'
      version '1.0'
      
      repositories {
          mavenLocal()
      }
      
      dependencies {
          implementation('org.springframework.boot:spring-boot-starter-web ')
      }
      
      

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