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<String,Object>();
    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 区别

apiimplementation
编译时能进行依赖传递,底层变,全部都要变、编译速度慢不能进行依赖传递,底层变,不用全部都要变,编译速度快
运行时运行时会加载,所有模块的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<Project>{
    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<Project>{
    @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 ')
      }
      
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值