当前位置:   article > 正文

一文了解Gradle构建工具_gradle打包可执行jar

gradle打包可执行jar

        Gradle 是一种开源构建自动化工具,可以构建几乎任何类型的软件。Gradle 对您要构建什么或如何构建它几乎没有任何假设。这使得 Gradle 特别灵活。Gradle 构建脚本是使用 Groovy 或 Kotlin DSL 编写的。在深入了解 Gradle 的细节之前,了解以下术语会很有帮助。

术语

  • 项目:Gradle 构建的东西。项目包含一个构建脚本,它是一个位于项目根目录中的文件,通常名为build.gradle或build.gradle.kts. 构建脚本为该项目定义任务、依赖项、插件和其他配置。单个构建可以包含一个或多个项目,每个项目可以包含自己的子项目。
  • 任务:任务包含执行某些工作的逻辑——编译代码、运行测试或部署软件。在大多数项目中使用Gradle提供的内置任务就足够了。比如TestGradle 提供了实现许多常见构建系统需求的任务,任务本身包括:
  • 动作:做某事的工作片段,例如复制文件或编译源代码
  • 输入:操作使用或操作的值、文件和目录
  • 输出:操作修改或生成的文件和目录
  • 插件:插件允许您将新概念引入到任务、文件和依赖配置之外的构建中。例如,大多数语言插件将源集的概念添加到构建中。使用插件,您可以编写一次任务并在多个构建中使用它。或者,您可以将常用配置(如日志记录、依赖项和版本管理)存储在一个位置,这可减少了构建脚本中的重复,大大提高易用性和效率。

一、构建工具分类

        常见的构建工具主要有三种:Ant、Maven、Gradle。Ant现在使用的不是太多,至少在国内是这样。如果对Maven已经非常熟悉了,可能不太愿意使用gradle,感觉貌似没有必要。但是既然gradle出现了就说明有很多人对Maven还是有一定的意见。因此在这里我来总结一下gradle相比maven的优势。

下图来源于官网:

  • 速度:gradle使用构建缓存、守护进程等方式提高编译速度。结果就是gradle的编译速度要远超maven,平均编译速度比Maven快好几倍,而且项目越大,这个差距就越明显。
  • 灵活性:gradle要比Maven灵活太多,虽然有时候灵活并不是一件好事情。但是大部分情况下,灵活一点可以极大的方便我们。Maven死板的XML文件方式做起事情来非常麻烦。很多Maven项目都通过执行外部脚本的方式来完成一些需要灵活性的工作。而在gradle中配置文件就是构建脚本,构建脚本就是编程语言,完全可以自给自足,无需外部脚本。
  • 简洁性:gradle脚本的长度要远远短于maven配置文件的长度。虽然很多人都说XML维护起来不麻烦,但是我觉得,维护一个光是依赖就有几百行的XML文件,不见得就比gradle脚本简单。

        也许是因为我上面说的原因,也许有其他原因,不得不承认的一件事情就是gradle作为一个新兴的工具已经有了广泛的应用。spring等项目已经从Maven切换到了gradle。开发安卓程序也只支持gradle了。因此不管是否现在需要将项目从maven切换到gradle,但是至少学习gradle是一件必要的事情。

二、安装Gradle

        安装 Gradle 之前首先要确保我们已经在系统中安装了 JDK,并且JDK的版本最低在1.7。最新的Gradle版本需要JDK1.8及以上,官网文档地址:​​https://docs.gradle.org/​​,详细可参考官方文档。如果是Java项目建议直接采用IDE方式安装,比如IntelliJ IDEA,IDEA不仅自带了Maven构建工具,还可以在创建项目的时候选择Gradle创建项目。

2.1、全局配置

        同Maven一样,安装成功后或是创建了一个Gradle项目后,一般会在当前系统用户的根目录下创建仓库。如下图所示,其中/Users/liudong/.gradle 就是Gradle的默认本地仓库地址,最初时没有gradle.properties和init.gradle这两个文件,需要手动添加,这两个文件就是全局配置文件。但建议每到一个公司就修改一个目录(习惯问题,可按个人习惯决定是否分开)​

  • cachs\modules-2:所有依赖的jar包的缓存目录;
  • wrapper\dists:所有下载的不同版本的Gradle存放地址目录;

配置全局仓库

        在gradle中配置下载镜像需要在/Users/liudong/.gradle文件夹中新建一个init.gradle初始化脚本,这样一来,gradle下载镜像的时候就会使用这里配置的镜像源下载,速度会快很多,脚本文件内容如下:

  1. allprojects {
  2. repositories {
  3. maven {
  4. url "https://maven.aliyun.com/repository/public"
  5. }
  6. maven {
  7. url "https://maven.aliyun.com/repository/jcenter"
  8. }
  9. maven {
  10. url "https://maven.aliyun.com/repository/spring"
  11. }
  12. maven {
  13. url "https://maven.aliyun.com/repository/spring-plugin"
  14. }
  15. maven {
  16. url "https://maven.aliyun.com/repository/gradle-plugin"
  17. }
  18. maven {
  19. url "https://maven.aliyun.com/repository/google"
  20. }
  21. maven {
  22. url "https://maven.aliyun.com/repository/grails-core"
  23. }
  24. maven {
  25. url "https://maven.aliyun.com/repository/apache-snapshots"
  26. }
  27. }
  28. }

配置Gradle参数

        在/Users/liudong/.gradle文件夹中直接新建一个gradle.properties文件,创建内容不复杂,直接看代码即可,设置Gradle的JVM参数、代理和日志等信息。更多的设置可查看官网。

  1. org.gradle.jvmargs=-Xmx4g -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
  2. systemProp.http.proxyHost=127.0.0.1
  3. systemProp.http.proxyPort=10800
  4. systemProp.https.proxyHost=127.0.0.1
  5. systemProp.https.proxyPort=10800
  6. systemProp.file.encoding=UTF-8
  7. org.gradle.warning.mode=all
  8. myProjectProp=HelloApp

        这些属性是可以在buid.gradle.kts中用命令取到的,比如:

  1. if (hasProperty("myProjectProp")) {
  2. // Accessing the value, throws if not present
  3. println(property("myProjectProp"))
  4. }

2.2、Intellij IDEA中创建Gradle项目

OS:MacOS Monterey 12.6.5

idea版本:IntelliJ IDEA 2023.1.1 (Ultimate),不同idea版本截图略有差异。

创建项目

        可以【create new project】新建项目,或在已有项目上【create new module】新建模块。建议使用Idea开发时,在源码的管理上可以先创建一个【Empty Project】,然后以module的方式引入源码。这样方便管理,不同的模块也可以有不同的配置方式。下图是在已有项目上创建了一个新模块。

Idea创建模块时所有设置就一个界面,详细解释如下,与构建项目相关的关键信息已标红:

  • 语言:项目的开发语言,是什么项目就选什么语言即可;
  • 构建系统:必须选择 Gradle;
  • JDK:项目的JDK,并不是Gradle依赖的JDK,按项目要求选择相应的版本即可,后续可以在脚本中修改;
  • Gradle DSL:Gradle的构建脚本是可编程的,此处是指定Gradle的开发语言,但现在一般的项目都推荐使用Kotlin语言,注意,不同语言生成的构建文件类型不一样,Groovy生成的配置文件以.gradle结尾,选择Kotlin时配置文件以.gradle.kts结尾。
  • 父项:相当于maven构建时的parent父项目的意思,后续可以在脚本中修改;
  • Gradle分发:选择包装器Gradle Wrapper,后面会着重介绍;
  • Gradle版本:默认即可,后续可以在脚本中修改;
  • 组ID和工件ID:其实就是类似maven中的groupId和artifactId,后续可以在脚本中修改;

配置好后,点击【创建】会生成如下图所示目录结构:

  • .gradle:与gradle相关的支撑缓存文件夹和项目编译等无了,不需要关注。
  • gradle:gradle的包装器,下一节会详细说明
  • build.gradle:Gradle与项目相关的配置文件,配置项目依赖、打包、插件等,相当于maven的pom.xml文件;
  • gradlew:适用于linux和mac系统的Gradle 启动脚本文件;
  • gradlew.bat: 适用于windows系统Gradle 启动脚本文件;
  • setting.gradle: 添加编译的所有模块;

配置项目

        点开IDEA的【首选项】,找到如下图所示的配置页面,按需修改红框内的内容即可:

  • Gradle用户主目录:个人习惯是每到一个新公司就设置一个专门的主目录;
  • 使用此工具构建和运行:建议改成 Intellij IDEA;
  • 使用此工具运行测试:建议改成 Intellij IDEA;
  • Gradle JVM:Gradle运行依赖的JDK环境,注意区分不要和项目的JDK弄混;

项目个性化gradle.properties配置

        可以项目根路径下同样配置一个名为gradle.properties的文件,大体配置如下:

  1. #性能配置
  2. kotlin.incremental.useClasspathSnapshot = false
  3. kotlin.stdlib.default.dependency = false
  4. org.gradle.configuration-cache = true
  5. org.gradle.caching = true
  6. systemProp.org.gradle.unsafe.kotlin.assignment = true

        其它几个常用的配置如下:

  • org.gradle.unsafe.configuration-cache = true:开启gradle缓存,加快构建速度
  • org.jetbrains.intellij.buildFeature.selfUpdateCheck=false:设置插件是否自动更新检查
  • org.jetbrains.intellij.buildFeature.buildSearchableOptions=false:禁止为插件生成索引信息
  • org.jetbrains.intellij.buildFeature.paidPluginSearchableOptionsWarning=false:如果插件为付费的,设置是否可搜索;
  • kotlin.incremental.useClasspathSnapshot=false:Kotlin 编译器抛出内存不足时的解决方法
  • kotlin.stdlib.default.dependency = false:如果Kotlin版本大于1.4设置成false,否则设置成true
  • runIde.autoReloadPlugins = true:修改插件后可重新运行build插件,这样就会自动更新了

开发语言配置

java

  1. plugins {
  2. id("java")
  3. }
  4. java {
  5. sourceCompatibility = JavaVersion.VERSION_17
  6. targetCompatibility = JavaVersion.VERSION_17
  7. }
  8. tasks {
  9. withType<JavaCompile> {
  10. sourceCompatibility = "17"
  11. targetCompatibility = "17"
  12. }
  13. }

kotlin

  1. plugins {
  2. id("java")
  3. id("org.jetbrains.kotlin.jvm") version "1.8.21"
  4. }
  5. java {
  6. sourceCompatibility = JavaVersion.VERSION_17
  7. }
  8. tasks {
  9. compileKotlin {
  10. kotlinOptions.jvmTarget = "17"
  11. }
  12. compileTestKotlin {
  13. kotlinOptions.jvmTarget = "17"
  14. }
  15. }

java与kotlin互转

java2kotlin

        选择特定的.java文件后,选择菜单栏【code】-【convert java to kotlin】

kotlin2java

        选择特定的.kt文件后,选择菜单栏【tool】-【kotlin】-【show kotlin bytecode】,在弹出窗口上选择【反编译】,如下图:

2.3、Gradle Wrapper配置

可以称Gradle Wrapper为Gradle包装器,是将Gradle再次包装。让所有的Gradle构建方法在 Gradle 包装器的帮助下运行。目的是可以让我们不需要在电脑中安装 Gradle 环境也可以运行 Gradle 项目。官方建议任何 Gradle 构建方法在 Gradle Wrapper帮助下运行,利于多人协同开发时环境的统一。

  • gradle-wrapper.jar: 既然是 jar 包,那么它肯定是包含了 Gradle 运行时的逻辑代码;
  • gradle-wrapper.properties: 这个文件主要负责配置Gradle wrapper运行时的属性文件,声明具体使用哪个版本的 Gradle,详细配置如下:
  1. #Gradle根目录,默认根目录是/Users/userName/.gradle/;
  2. distributionBase=GRADLE_USER_HOME
  3. #distributionBase+distributionPath就是Gradle解包后的存放的具体目录
  4. distributionPath=wrapper/dists
  5. #Gradle项目中用到的Gradle版本,如果你使用IDEA的话推荐下载all版,这样可以分析源代码进而提供更加精确的gradle脚本支持
  6. distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip
  7. #Gradle压缩包下载后存储父目录
  8. zipStoreBase=GRADLE_USER_HOME
  9. #zipStoreBase+zipStorePath就是 Gradle 压缩包的存放位置
  10. zipStorePath=wrapper/dists

三、执行Gradle命令

Gradle和Maven一样,有两种执行方式,依拖相关的IDE提供的图形化界面或是命令行;

3.1、IdeaPlugin-UI操作

命令都比较简单,在IDEA右侧选择相应的Gradle项目,所有可执行的命令都在Tasks下面,双击即可。最下面的【运行配置】是一个快捷操作,保存了最近操作过的命令。

3.2、IdeaPlugin-Command操作

3.3、gradleWrapper命令行操作

因为采用的是Gradle Wrapper模式,电脑中并没有安装 Gradle 环境(其实也不建议安装),所以原始的Terminal并没gradle这个命令,需要借助项目根目录下的gradlew(linux和mac) 和 gradlew.bat(windows)文件。首先打开命令行切换到当前项目的根目录下,然后执行相关的命令:./gradlew xxxx  。

3.4、GradleWrapper常用命令

查看版本信息

  1. (base) MacBook:gradleLession liudong$ ./gradlew -v
  2. ------------------------------------------------------------
  3. Gradle 8.0
  4. ------------------------------------------------------------
  5. Build time: 2023-02-13 13:15:21 UTC
  6. Revision: 62ab9b7c7f884426cf79fbedcf07658b2dbe9e97
  7. Kotlin: 1.8.10
  8. Groovy: 3.0.13
  9. Ant: Apache Ant(TM) version 1.10.11 compiled on July 10 2021
  10. JVM: 1.8.0_144 (Oracle Corporation 25.144-b01)
  11. OS: Mac OS X 10.16 x86_64

查看项目模块

  1. (base) MacBook:gradleLession liudong$ ./gradlew -q projects
  2. ------------------------------------------------------------
  3. Root project 'gradleLession'
  4. ------------------------------------------------------------
  5. Root project 'gradleLession'
  6. No sub-projects
  7. To see a list of the tasks of a project, run gradlew <project-path>:tasks
  8. For example, try running gradlew :tasks

查看项目依赖列表

  1. (base) MacBook:gradleLession liudong$ ./gradlew dependencies
  2. > Task :dependencies
  3. ------------------------------------------------------------
  4. Root project 'gradleLession'
  5. ------------------------------------------------------------
  6. annotationProcessor - Annotation processors and their dependencies for source set 'main'.
  7. No dependencies
  8. compileClasspath - Compile classpath for source set 'main'.
  9. +--- org.projectlombok:lombok:1.18.26
  10. \--- mysql:mysql-connector-java:8.0.32
  11. \--- com.mysql:mysql-connector-j:8.0.32
  12. \--- com.google.protobuf:protobuf-java:3.21.9
  13. ...省略
  14. A web-based, searchable dependency report is available by adding the --scan option.
  15. BUILD SUCCESSFUL in 531ms
  16. 1 actionable task: 1 executed

查看指定构建任务的依赖

  1. ./gradlew -q dependencies api:dependencies
  2. ./gradlew -q api:dependencies --configuration testCompile

获取特定依赖信息

  1. gradle -q webapp:dependencyInsight --dependency groovy --configuration compile
  2. org.codehaus.groovy:groovy-all:2.2.0
  3. — project :api
  4. compile

获取项目属性列表

  1. \> ./gradlew -q api:properties
  2. \------------------------------------------------------------
  3. Project :api - The shared API for the application
  4. \------------------------------------------------------------
  5. allprojects: [project ':api']
  6. ant: org.gradle.api.internal.project.DefaultAntBuilder@12345
  7. antBuilderFactory: org.gradle.api.internal.project.DefaultAntBuilderFactory@12345
  8. artifacts: org.gradle.api.internal.artifacts.dsl.DefaultArtifactHandler@12345
  9. asDynamicObject: org.gradle.api.internal.ExtensibleDynamicObject@12345
  10. buildDir: /home/user/gradle/samples/userguide/tutorial/projectReports/api/build
  11. buildFile: /home/user/gradle/samples/userguide/tutorial/projectReports/api/build.gradle

查看所有任务

  1. (base) MacBook:gradleLession liudong$ ./gradlew task
  2. > Task :tasks
  3. ------------------------------------------------------------
  4. Tasks runnable from root project 'gradleLession'
  5. ------------------------------------------------------------
  6. Build tasks
  7. -----------
  8. assemble - Assembles the outputs of this project.
  9. build - Assembles and tests this project.
  10. buildDependents - Assembles and tests this project and all projects that depend on it.
  11. buildNeeded - Assembles and tests this project and all projects it depends on.
  12. classes - Assembles main classes.
  13. clean - Deletes the build directory.
  14. jar - Assembles a jar archive containing the main classes.
  15. testClasses - Assembles test classes.
  16. ...省略

跳过指定任务

  1. //buid.gradle中定义的Task,mTest
  2. task mTest{
  3. doLast{
  4. println "这是测试Task"
  5. }
  6. }
  7. //在控制台执行命令排除
  8. $ gradle clean build -x mTest

生成构建报告

        分析项目构建过程,主要是一些耗时等信息。我们看到控制台它会输出已生成 HTML 格式和 XML 格式的文档。

  1. (base) MacBook:gradleLession liudong$ ./gradlew --profile build
  2. BUILD SUCCESSFUL in 1s
  3. 2 actionable tasks: 2 executed
  4. See the profiling report at: file:///Users/liudong/ideaWS/ideaplugin/gradleLession/build/reports/profile/profile-2023-05-12-22-30-15.html
  5. A fine-grained performance profile is available: use the --scan option.

        上图中第6行就是生成的报告的地址,也可以在项目根目录下的build/reports/profile目录下找到报告的.html文件,打开后如下图所示:

项目打包

引入打jar包插件

        如果想打war包,只面引入以下插件即可:

apply plugin: 'war'

引入打war包插件

        如果想打war包,只面引入以下插件即可:

apply plugin: 'war'

打包

        编译并打包 jar 文件,但不会执行单元测试,用的是assemble命令。一些其他插件可能会增强这个任务的功能。例如,如果采用了 War 插件,这个任务便会为你的项目打出 War 包。

  1. // 编译并打Debug包
  2. $ gradle assembleDebug
  3. // 编译app module 并打Debug包
  4. $ gradlew install app:assembleDebug
  5. // 编译并打Release的包
  6. # gradle assembleRelease
  7. // 编译并打Release包并安装
  8. $ gradle installRelease
  9. // 卸载Release
  10. $ gradle uninstallRelease

指定main.class

        指定应用是一个app,然后指定Hello为main.java。

  1. plugins {
  2. id("application")
  3. }
  4. application {
  5. mainClass.set("com.example.Hello")
  6. }

把依赖打到jar包中

  1. tasks {
  2. // 将依赖打进jar包中
  3. jar.configure {
  4. duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.INCLUDE
  5. from(configurations.runtimeClasspath.get().filter { it.name.endsWith("jar")}.map { zipTree(it) })
  6. }
  7. }

私服发布

        需要修改build.gradle文件,详细代码如下,然后执行右侧 publishing 命令。

  1. plugins {
  2. id 'java-library'
  3. id 'maven-publish'
  4. }
  5. publishing {
  6. publications {
  7. myLibrary(MavenPublication) {
  8. from components.java
  9. }
  10. }
  11. repositories {
  12. maven {
  13. // default credentials for a nexus repository manager
  14. credentials {
  15. username 'admin'
  16. password 'xxxxx'
  17. }
  18. allowInsecureProtocol = true //允许http
  19. // 发布maven存储库的url
  20. url "http://localhost:8080/nexus/content/repositories/releases/"
  21. }
  22. }
  23. }

其它常用命令参数

gradle -Dorg.gradle.logging.level=warn clean

-Dorg.gradle.logging.level=(quiet,warn,lifecycle,info,debug)

四、Gradle的生命周期

gradle 构建的生命周期主要分为三个阶段,Initialization,Configuration,Execution。

  • Initialization:Gradle支持单个或多个工程的构建。在Initialization阶段,Gradle决定哪些工程将参与到当前构建过程,并为每一个这样的工程创建一个Project实例。一般情况下,参与构建的工程信息将在settings.gradle中定义。
  • Configuration:在这一阶段,配置project的实例。所有工程的构建脚本都将被执行。Task,configuration和许多其他的对象将被创建和配置。
  • Execution:在之前的configuration阶段,task的一个子集被创建并配置。这些子集来自于作为参数传入gradle命令的task名字,在execution阶段,这一子集将被依次执行。

五、依赖管理

        大体的配置如下所示:

  1. plugins {
  2. id 'org.springframework.boot' version '2.7.4'
  3. id 'java'
  4. }
  5. group = 'com.zd'
  6. version = '1.0-SNAPSHOT'
  7. repositories {
  8. mavenLocal()
  9. maven { url "https://maven.aliyun.com/nexus/content/repositories/central/" }
  10. mavenCentral()
  11. }
  12. dependencies {
  13. testImplementation 'junit:junit:4.13'
  14. implementation 'org.projectlombok:lombok:1.18.26'
  15. implementation 'mysql:mysql-connector-java:8.0.32'
  16. }
  17. buildscript {
  18. ext {
  19. springBootVersion = "2.3.3.RELEASE"
  20. }
  21. repositories {
  22. mavenLocal()
  23. maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
  24. jcenter()
  25. }
  26. dependencies {
  27. classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
  28. }
  29. }
  30. apply plugin: 'java'
  31. apply plugin: 'org.springframework.boot'

项目配置

         和发布打包相关的一些配置。

  1. group = 'com.zd'
  2. version = '1.0-SNAPSHOT'

插件配置

        gradle插件类似于maven插件,plugins闭包(标签)里的插件必须是gradle官方插件库(​​http://plugins.gradle.org​​​)里的,另外plugins块不能放在多项目配置块(allProjects, subProjects)里。另外因为java是核心插件,所以不用指定版本,而其它的插件比如org.springframework.boot是社区插件,所以必须指定版本。

  1. plugins {
  2. id 'org.springframework.boot' version '2.7.4'
  3. id 'java'
  4. }

buildscript配置

        buildscript中的声明是gradle脚本自身需要使用的资源。可以声明的资源包括依赖项、第三方插件、maven仓库地址等。而在build.gradle文件中直接声明的依赖项、仓库地址等信息是项目自身需要的资源。gradle在执行脚本时,会优先执行buildscript代码块中的内容,然后才会执行剩余的build脚本。

        buildscript代码块中的repositories和dependencies的使用方式与直接在build.gradle文件中的使用方式几乎完全一样。唯一不同之处是在buildscript代码块中你可以对dependencies使用classpath声明。该classpath声明说明了在执行其余的build脚本时,class loader可以使用这些你提供的依赖项。这也正是我们使用buildscript代码块的目的。某种意义上来说,classpath 声明的依赖,不会编译到最终的jar包里面

另外,buildscript必须位于plugins块和apply plugin之前

  1. buildscript {
  2. ext {
  3. springBootVersion = "2.3.3.RELEASE"
  4. }
  5. repositories {
  6. mavenLocal()
  7. maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
  8. jcenter()
  9. }
  10. dependencies {
  11. classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
  12. }
  13. }
  14. apply plugin: 'java'
  15. apply plugin: 'org.springframework.boot'

        注意上面代码中的ext代码块,ext代码块是提供给用户自定义属性用的,一般用来定义版本,实现版本的集中管理

仓库配置

        gradle仓库可以直接使用maven的仓库,但是gradle下载的jar包文件格式与maven不一样,所以不能和maven本地仓库共用,仓库的配置,是在repository中的:

  1. repositories {
  2. mavenLocal() //本地仓库
  3. maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } //外部仓库(阿里云)
  4. mavenCentral() // maven 中心仓库
  5. }

jar依赖配置

        gradle依赖写在dependcies代码块中,gradle中引入依赖只需要一行,遵循​​scope 'gropId:artifactId:version'​​的格式,也可以是​​scope (gropId:artifactId:version)​

  1. dependencies {
  2. testImplementation 'junit:junit:4.13'
  3. implementation 'org.projectlombok:lombok:1.18.26'
  4. implementation 'mysql:mysql-connector-java:8.0.32'
  5. }
  1. dependencies {
  2. testImplementation('junit:junit:4.13')
  3. implementation('org.projectlombok:lombok:1.18.26')
  4. implementation('mysql:mysql-connector-java:8.0.32')
  5. }

maven只有compile、provided、test、runtime,而gradle有以下几种scope:

  • implementation:默认的scope,会将指定的依赖添加到编译路径,并且会将该依赖打包到输出,但是这个依赖在编译时不能暴露给其他模块,例如如果我们的类库包含了gson,那么其他人使用我们的类库时,编译时不会出现gson的依赖。
  • api:api关键字是由java-library提供,若要使用,请在plugins中添加:​​id 'java-library'​​== (在旧版本中作用与compile相同,新版本移除了compile)使用api配置的依赖会将对应的依赖添加到编译路径,并将依赖打包输出,但是这个依赖是可以传递的,比如模块A依赖模块B,B依赖库C,模块B在编译时能够访问到库C,但是与implemetation不同的是,在模块A中库C也是可以访问的。
  • compileOnly:compileOnly修饰的依赖会添加到编译路径中,但是不会被打包,因此只能在编译时访问,且compileOnly修饰的依赖不会传递。
  • runtimeOnly:这个与compileOnly相反,它修饰的依赖不会添加到编译路径中,但是能被打包,在运行时使用。和Maven的provided比较接近。
  • annotationProcessor:用于注解处理器的依赖配置。
  • testImplementation:这种依赖在测试编译时和运行时可见,类似于Maven的test作用域。
  • testCompileOnly和testRuntimeOnly:这两种类似于compileOnly和runtimeOnly,但是作用于测试编译时和运行时。
  • classpath:见上一段,classpath并不能在buildscript外的dependcies中使用

排除依赖包中的依赖

        我们开发中,可能大家或多或少都会遇到 jar 包冲突的问题,有时候两个 jar 包不同,但是里面有两个类的包名路径是一摸一样的。这样我们就需要排除掉某个包中的重复的类,这时候就需要用的 exclude 命令,如下例子:

  1. compile('org.hibernate:hibernate:3.1') {
  2. //以artifact name来排除出
  3. exclude module: 'cglib'
  4. //通过group name来排除
  5. exclude group: 'org.jmock'
  6. }

排除环境依赖

  1. configurations {
  2. runtime.exclude group: "org.slf4j", module: "slf4j-log4j12"
  3. compile.exclude group: "org.slf4j", module: "slf4j-log4j12"
  4. }

全局排除依赖

  1. configurations.all {
  2. exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
  3. }

六、多模块项目搭建

6.1、项目搭建

新建父工程

        按下图创建一个新的项目,注意要选择【新建项目】,然后删除项目中的src文件夹。

新建子模块

        如下图所示,注意下图中的父项要选b2bdemo。

        经过以上两部后,项目的目录情况如下图所示:

项目工程设置

      统一由settings.gradle文件管理,配置文件如下所示,其它文件没有特殊的地方,注意groovy和kts的写法,一般就是差个(),然后把'改成":

  1. rootProject.name = 'b2bdemo'
  2. include 'api'
  3. include 'server'
  1. rootProject.name = "b2bdemo"
  2. include("api")

        另外可以有更多的配置管理,比如:

  1. include("project-a")
  2. project(":project-a").projectDir = file("../my-project-a")
  3. project(":project-a").buildFileName = "project-a.gradle"

6.2、父工程配置

        build.gradle配置

  1. allprojects{ // 所有模块的配置
  2. group = 'org.example'
  3. version = '0.0.1'
  4. repositories {
  5. mavenLocal()
  6. maven { url 'https://maven.aliyun.com/repository/public/' }
  7. mavenCentral()
  8. }
  9. //指定编码格式
  10. tasks.withType(JavaCompile) {
  11. options.encoding = "UTF-8"
  12. }
  13. //这里的clean它是一个 Gradle 任务,它继承自Delete,执行clean命令时删除build文件夹下的内容。
  14. task clean(type: Delete) {
  15. delete rootProject.buildDir
  16. }
  17. }
  18. subprojects { //子模块配置
  19. apply plugin: "java"
  20. apply plugin: 'java-library'
  21. apply plugin: "idea" //指定编辑器
  22. //java版本
  23. sourceCompatibility = 1.8
  24. targetCompatibility = 1.8
  25. //公共依赖
  26. dependencies {
  27. compileOnly 'org.projectlombok:lombok:1.18.20'
  28. annotationProcessor 'org.projectlombok:lombok:1.18.20'
  29. }
  30. }

多模块依赖管理

        在7.0+版本,gradle提供了dependencyResolutionManagement来进行多模块之间的依赖共享,类似于maven的dependencyManagement:

第一步:

在7.4以下版本启用该功能,得在​​settings.gradle​​中添加​​enableFeaturePreview('VERSION_CATALOGS')​​,在​​settings.gradle​​中添加:

  1. dependencyResolutionManagement{
  2. versionCatalogs{
  3. libs{ //libs名字可以任意取,最好为libs,到8.0可能会强制使用libs
  4. library('hutool-core','cn.hutool:hutool-core:5.8.6')
  5. //library在7.4以下版本为alias在7.4+版本被弃用,并且alias用法与library略有区别,详情参考文末链接
  6. }
  7. }
  8. }

​l        ibrary第一个字符串为依赖的别名,注意别名必须由一系列以破折号(​​-​​,推荐)、下划线 (​​_​​) 或点 (​​.​​) 分隔的标识符组成(当然,不写分隔符也可以)。标识符本身必须由​​ascii​​字符组成,最好是小写,最后是数字。

第二步:

之后,便可以在子模块build.gradle中使用:

  1. dependencies {
  2. implementation(libs.hutool.core)
  3. }

同版本参数设置

        如果几个依赖共用一个版本,可以使用version来统一管理版本(注意,library中groupid与artifactid用‘,’隔开了),dependencies中用法一致

  1. dependencyResolutionManagement{
  2. versionCatalogs{
  3. libs{
  4. version('hutool','5.8.6')
  5. library('hutool-core','cn.hutool','hutool-core').versionRef('hutool')
  6. library('hutool-http','cn.hutool','hutool-http').versionRef('hutool')
  7. library('hutool-json','cn.hutool','hutool-json').versionRef('hutool')
  8. }
  9. }
  10. }

依赖批量引入

        要是不想一个个引用这几依赖的话,还可以使用bundles将几个依赖绑定到一起,一次性引入多个依赖:

  1. dependencyResolutionManagement{
  2. versionCatalogs{
  3. libs{
  4. version('hutool','5.8.6')
  5. library('hutool-core','cn.hutool','hutool-core').versionRef('hutool')
  6. library('hutool-http','cn.hutool','hutool-http').versionRef('hutool')
  7. library('hutool-json','cn.hutool','hutool-json').versionRef('hutool')
  8. bundle('hutool',['hutool-core','hutool-http','hutool-json'])
  9. }
  10. }
  11. }

        在子模块的build.gradle中的dependencies中:

  1. dependencies {
  2. implementation(libs.bundles.hutool)
  3. }

插件共享

  1. dependencyResolutionManagement{
  2. versionCatalogs{
  3. libs{
  4. plugin('spring-dependency','io.spring.dependency-management').version('1.0.14.RELEASE')
  5. }
  6. }
  7. }

6.3、模块之间的运行依赖

        只需要在dependencies中按照如下格式依赖即可,并且也是遵循依赖引入的几种scope规则的,要注意的是,被引用项目的类必须在软件包下,才可以被找到,下例代码中的:server为一个项目模块。

  1. dependencies {
  2. testImplementation platform('org.junit:junit-bom:5.9.1')
  3. testImplementation 'org.junit.jupiter:junit-jupiter'
  4. implementation(':server')
  5. }
implementation(project(":server"))

6.4、模块间的构建依赖

        在setting.gradle.kts中配置,

  1. rootProject.name = "my-composite"
  2. includeBuild("my-app")
  3. includeBuild("my-utils")

        然后在子模块中配置task,这样在构建子模块之前会先执行模块my-app的任务。

  1. tasks.register("run") {
  2. dependsOn(gradle.includedBuild("my-app").task(":app:run"))
  3. }

七、自定义Task

        一般定义在build.gradlw.kts文件中。详细参考​​文件处理​

7.1、定义简单任务

        自定义的任务会显示在idea右侧工具栏的other标签中,双击就可以运行。

  1. tasks.register("testBoth") {
  2. doFirst {
  3. println("This is executed first during the execution phase.")
  4. }
  5. doLast {
  6. println("This is executed last during the execution phase.")
  7. }
  8. println("This is executed during the configuration phase as well, because :testBoth is used in the build.")
  9. }
  10. //gradle -q testBoth
  11. 执行顺序是 println, first, last, -q表示不打印日志

7.2、使用预置好的任务

        这里的Copy是Gradle插件带的一些快捷工具,下面代码表示使用Copy工具定义一个名为copyReportsDirForArchiving的任务,复制文件。类似的还有zip、delete等。

  1. tasks.register<Copy>("copyReportsDirForArchiving") {
  2. from(layout.buildDirectory.dir("reports"))
  3. into(layout.buildDirectory.dir("toArchive"))
  4. }

7.3、复写当前任务

  1. tasks.register<Delete>("cleanOutDir") {
  2. dependsOn(":clean")
  3. delete(rootProject.buildDir.path + "/../out")
  4. }

7.4、模块间任务共享

  1. // demo.gradle
  2. task showProjectName{
  3. doLast {
  4. println("$project.name")
  5. }
  6. }
  7. showProjectName.enabled = false//禁用任务
  1. // demo1.gradle
  2. apply from: '../demo.gradle'
  1. //运行,使用任务全拼
  2. $ gradle showProjectName

八、常见问题

gradle lombok找不到符号?

        一般在build.gradle.kts中做如下配置,同时检查下Gradle配置

  1. compileOnly("org.projectlombok:lombok:1.18.26")
  2. annotationProcessor("org.projectlombok:lombok:1.18.26")
  3. testCompileOnly("org.projectlombok:lombok:1.18.26")
  4. testAnnotationProcessor("org.projectlombok:lombok:1.18.26")

如果还不行再检查下以下配置(正常来讲不需要做如下的改动,具体原因没查,需要试):

  • File => Settings => Build, Execution, Deployment => Compiler => Annotation Processors => Enable annotation processing
  • 调整编译器:由javac >> Eclipse,启用方法:File => Settings => Build, Execution, Deployment => Compiler => Java Compiler =>Use compiler Eclipse
  • 在项目的根目录下面,添加如下内容的:lombok.config文件
  1. # lombok.config
  2. # 声明该配置文件是一个根配置文件,从该配置文件所在的目录开始扫描
  3. config.stopBubbling=true
  4. # 全局配置 equalsAndHashCode 的 callSuper 属性为true
  5. lombok.equalsAndHashCode.callSuper=call
  • 部署在jenkins上面需要注释掉: annotationProcessor和testAnnotationProcessor

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/293458
推荐阅读
相关标签
  

闽ICP备14008679号