前言

背景介绍

Gradle是一个构建工具,面向开发者的脚本语言是GroovyKotlin,简而言之就是我们常用的build.gradle和build.gradle.kts或plugin等。

  • Groovy:主流语言,新建项目的时候,Groovy是默认的构建脚本语言
  • Kotlin:Gradle 5.0之后已经支持

在Gradle中,有大量配置都是通过脚本语言来写的,所以不管是Groovy还是Kotlin,最后的表现都是DSL(Domain Specific Language)

Gradle中的DSL

# 声明引入Gradle插件plugin的DSL代码
plugins {
    id 'java'
    id 'org.springframework.boot' version '2.5.3' apply 'false'
}

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

repositories {
    mavenCentral()
}

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

plugin 有id三个参数配置项:

  • id:调用的是PluginDependenciesSpec中的id(String id)函数,返回PluginDependencySpec对象,PluginDependencySpec对象可以理解为是PluginDependenciesSpec的一层封装,versionapply被封装在此对象中
  • version:插件的版本号,默认插件无须填写版本号,第三方插件需要填写版本号
  • apply:是否将插件应用于当前项目及子项目,默认是true,就是就是控制依赖传递的,当不想传递时可以设置为false

Kotlin写法

注意:只介绍引入包一种语法的不同之处

plugins {
    id("com.android.application") version "7.3.0" apply false
}

我们可以看出来,其实Kotlin DSLGroovy DSL的写法差别不大,也是调用PluginDependenciesSpec中的id(String id)函数,只不过差别在调用id(String id)函数时有显式的括号而已。

Gradle安装

下载安装包

从官网下载安装包,然后再本地解压:

配置系统环境变量

GRADLE_HOME:gradle压缩包解压后的目录
GRADLE_USER_HOME:gradle默认的仓库地址 Path:在末尾追加%GRADLE_HOME%/bin

测试

打开CMD命令窗口,输入gradle -v有如图输出,表示安装成功:

在IDEA内创建Gradle项目

Gradle项目结构

  1. settings.gradle 配置项目名,模块间的依赖
  2. build.gradle 配置项目groupId、version、依赖的gradle插件、jar包、jar仓库
  3. gradle/wrapper/gradle-wrapper.properties 配置当前项目使用的gradle软件版本、及下载目录
  4. build目录 项目打包的输出目录

编译打包

打开idea右侧的Gradle菜单,Tasks/build子菜单下有一组gradle指令,可以使用jar指令打包项目。打包结果输出在build目录:

Gradle配置国内的源

国内镜像感觉aliyun的比较全,最新地址如下:
developer.aliyun.com/mvn/view

在build.gradle中修改镜像地址配置:

  repositories {
    maven{ url 'https://maven.aliyun.com/repository/central' }
    maven{ url 'https://maven.aliyun.com/repository/public' }
    maven{ url 'https://maven.aliyun.com/repository/gradle-plugin'}
  }

注意:如果项目中引用了gradle plugin包,必须加入https://maven.aliyun.com/repository/gradle-plugin,不然在central仓库中找不到。如果有

maven 项目秒变Gradle项目

切到maven项目pom文件所在的目录,然后执行如下命令:

#1.7写法
gradle  setupBuild --type pom 
#2.0写法
gradle init --type pom 

常用SpringBoot Gradle的配置案例

/****************************************
 * gradle.properties
 * 各dependency的版本
 */
springBootVersion = 2.0.3.RELEASE
springVersion = 5.0.7.RELEASE

protobufPluginVersion = 0.8.6
protobufJavaVersion = 3.6.0
grpcPluginVersion = 1.14.0 # same to grpcVersion
grpcVersion = 1.14.0

guavaVersion = 25.1-jre

mysqlConnectorVersion = 6.0.6

lombokVersion = 1.18.2

/****************************************
 * repo配置
 * 相关nexus配置参见~/.gradle/gradle.properties: nexus.url nexus.username nexus.password
 */
buildscript {
    // repositories for plugins in build script
    repositories {
        mavenLocal()
        maven {
            name "nexus"
            url property("nexus.url")
            credentials {
                username property("nexus.username")
                password property("nexus.password")
            }
        }
    }
}
// repositories for project dependencies
repositories {
    mavenLocal()
    maven {
        name "nexus"
        url property("nexus.url")
        credentials {
            username property("nexus.username")
            password property("nexus.password")
        }
    }
}

/****************************************
 * SpringBoot基本配置
 */
buildscript {
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

// spring 2.+
bootJar.archiveName="${project.name}-boot.jar"
task('release', type: Copy) {
    dependsOn bootJar
    from("$buildDir/libs/") {
        include "${project.bootJar.archiveName}"
    }

    String date = "date +%Y%m%d".execute().text.trim()
    String baseDir = date + "_" + project.version
    String defaultDir = "/global/release/${project.name}/$baseDir"
    String dir = defaultDir
    if (project.hasProperty("dir")) {
        dir = project.property("dir")
    }
    into "$dir"
    doLast {
        println ". release into: ${project.release.destinationDir}/${project.bootJar.archiveName}"
    }
}

/****************************************
 * SpringBoot的Configuration Processor
 * 并将metadata.json拷贝到resources目录,以便在IDEA中起效
 */
// copy spring-configuration-metadata.json when it's generated
compileJava << {
    project.copy {
        from("${sourceSets.main.java.outputDir}/META-INF") {
            include "*.json"
        }
        into "src/main/resources/META-INF"
    }
}
// 依赖spring-boot-configuration-processor
dependencies {
    // gradle 官方推荐的方式
    annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
    // 避免IDEA的警告,不过不加也没关系
    compileOnly("org.springframework.boot:spring-boot-configuration-processor")
}

/****************************************
 * 常用的java task
 */
task sourcesJar(type: Jar, dependsOn: classes) {
    from sourceSets.main.allJava
    classifier = 'sources'
    doLast {
        println archivePath
    }
}
task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
    doLast {
        println archivePath
    }
}

/****************************************
 * 输出task结果
 */
jar << {
    println archivePath
}
test << {
    println reports.html.entryPoint
}
jacocoTestReport << {
    println reports.html.entryPoint
}

/****************************************
 * lombok
 */
dependencies {
    // lombok,两种方式依赖都需要
    annotationProcessor("org.projectlombok:lombok:$lombokVersion")
    compileOnly("org.projectlombok:lombok:$lombokVersion")
}

/****************************************
 * proto module的配置
 */
buildscript {
    dependencies {
        classpath "com.google.protobuf:protobuf-gradle-plugin:$protobufPluginVersion"
    }
}
apply plugin: "java-library"
apply plugin: "com.google.protobuf"
// protobuf setting
protobuf {
    // change generated directory
    generatedFilesBaseDir = "$projectDir/gen/"
    def userhome = System.properties['user.home']
    plugins {
        // define a codegen plugin named as `naming`
        naming {
            path = "$userhome/.protobuf/naming.py"
        }
        grpc {
            artifact = "io.grpc:protoc-gen-grpc-java:$grpcPluginVersion"
        }
    }
    generateProtoTasks {
        ofSourceSet('main')
        // all() returns the collection of all protoc tasks
        all().each { task ->
            // Here you can configure the task by name of each codegen plugin
            // change output sub-directory to put all generated files together
            task.plugins {
                naming {
                    outputSubDir = "java"
                }
                grpc {
                    outputSubDir = "java"
                }
            }
        }
    }
}
clean {
    // remove protobuf generated files when clean
    delete protobuf.generatedFilesBaseDir
}
sourceSets {
    // add protobuf generated files into sourceSet automatically
    main.java.srcDir("${protobuf.generatedFilesBaseDir}/main/java")
}
apply plugin: 'idea'
idea {
    module {
        // mark protobuf source directory as source root
        sourceDirs += sourceSets.main.proto.sourceDirectories
    }
}
task('protoZip', type: Zip) {
    from sourceSets.main.proto
    classifier = 'proto'
    doLast {
        println archivePath
    }
}
// publish proto zip if necessary
afterEvaluate {
    project.publishing.publications {
        mavenJava(MavenPublication) {
            // 发布proto包
            artifact protoZip
        }
    }
}
// protobuf dependencies
dependencies {
    // protobuf dependency
    api("com.google.protobuf:protobuf-java:$protobufJavaVersion")
    // grpc dependencies
    api("io.grpc:grpc-protobuf:$grpcVersion")
    api("io.grpc:grpc-stub:$grpcVersion")
}
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐