Gradle (史上最全): 5W字文

Posted 40岁资深老架构师尼恩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gradle (史上最全): 5W字文相关的知识,希望对你有一定的参考价值。

Gradle是绕不开的一个构建工具

对于用惯了 maven的人来说, Graddle不好用, 非常不好用, 主要是环境 会遇到各种各样的问题

但是,越来越多的 场景使用到了 Graddle,但是

  • spring 的源码,使用 Gradle 构建

  • elasticsearch 的源码,使用 Gradle 构建

  • caffeine 的源码,使用 Gradle 构建

接下来, 尼恩要带大家 完成一个 超级牛逼的 大厂offer 收割机项目—— 100Wqps 三级组件 实操,

实操中,用到 caffeine

并且,尼恩要带大家 穿透式 、起底式的 学习 caffeine 的源码和架构, 必须会用 Gradle

所以 Gradle 的文章,来了

关于 本文的代码,和技术问题, 请来尼恩 发起的Java 高并发 疯狂创客圈 社群交流 ,

什么是Gradle

Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,也增加了基于Kotlin语言的kotlin-based DSL,抛弃了基于XML的各种繁琐配置。

面向Java应用为主。当前其支持的语言C++、Java、GroovyKotlinScala和Swift,计划未来将支持更多的语言。

Projects 和 tasks

projects 和 tasks是 Gradle 中最重要的两个概念。

任何一个 Gradle 构建都是由一个或多个 projects 组成。

每个 project 包括许多可构建组成部分。 这完全取决于你要构建些什么。

举个例子,每个 project 或许是一个 jar 包或者一个 web 应用,它也可以是一个由许多其他项目中产生的 jar 构成的 zip 压缩包。一个 project 不必描述它只能进行构建操作。它也可以部署你的应用或搭建你的环境。

不要担心它像听上去的那样庞大。 Gradle 的 build-by-convention 可以让您来具体定义一个 project 到底该做什么。

每个 project 都由多个 tasks 组成。

每个 task 都代表了构建执行过程中的一个原子性操作。如编译,打包,生成 javadoc,发布到某个仓库等操作。

Hello world

你可以通过在命令行运行 gradle 命令来执行构建,gradle 命令会从当前目录下寻找 build.gradle 文件来执行构建。我们称 build.gradle 文件为构建脚本。

严格来说这其实是一个构建配置脚本,后面你会了解到这个构建脚本定义了一个 project 和一些默认的 task。

要尝试这一点,请创建以下名为 build.gradle 的构建脚本。

第一个构建脚本

build.gradle

task hello 
    doLast 
        println 'Hello world!'
    

关于 本文的代码,和技术问题, 请来尼恩 发起的Java 高并发 疯狂创客圈 社群交流 ,

快速定义任务

用一种更简洁的方式来定义上面的 hello 任务。

build.gradle

task hello 
    println 'Hello world!'

上面的脚本采用闭包的方式来定义了一个叫做 hello 的任务,

闭包也叫做代码块

在两个任务之间指明依赖关系

build.gradle

task foo  
    println 'crazy maker circle!'



task bar(dependsOn: foo)  
    println " a good circle"

关于 本文的代码,和技术问题, 请来尼恩 发起的Java 高并发 疯狂创客圈 社群交流 ,

为任务增加自定义属性

build.gradle

task myTask 
    ext.myProperty = "myValue"


task printTaskProperties << 
    println myTask.myProperty

关于 本文的代码,和技术问题, 请来尼恩 发起的Java 高并发 疯狂创客圈 社群交流

Gradle与maven的对比

Gradle作为基于Groovy语言的构建工具,与Gradle相比,ant显得冗长复杂,maven显得有些局促落后,但Gradle基于DSL语法,特点明显。 简洁、灵活、可读性强

1 .基本构成信息

maven使用. pom文件,

gradle使用. gradle文件基于XML,gradle使用Groovy,gradle使用maven需要固定配置的groupId、artfactId、软件包等基本参数

1 .依赖管理

Gradle的jar软件包管理支持maven的存储库方法和Ant的yedts方法。 因为maven的存储库非常成熟,所以Gradle与存储库兼容,所以非常方便。 定义maven的存储库: maven local ():maven本地库、mavenCentral ) ) : maven远程库、mavenRepo urls:自定义库路径

maven使用组id、名称和版本来查找与配置的资料档案库中指定的依

赖关系相关的Jar包。 虽然Gradle的生命周期更为复杂,但它也支持依赖于Maven的构建生命周期。 compile、runtime、testCompile和testRuntime分别支持项目各个阶段的依赖关系。 它还简化了maven的配置命令

2 .多项目管理

在实际使用中,大多数情况下,需要管理的不仅仅是一个项目。 maven使用依赖、继承和配置的概念,为父模块指定自己的子模块,并提供插件、配置信息等各子模块共有的资源。 通过将封装模块与实现具体功能的模块分开的方法,管理多个项目。

Gradle在这方面更明确,划分更明确,也更容易学习Gradle的多个项目管理。

在eclipse中安装Gradle插件后,创建新的Gradle项目,选择flat-Java-multi项目时,生成的项目就是多个项目管理的一个例子。

Gradle通过settings.Gradle文件指定项目的子项目,在构建初始化阶段(Initialization ),Gradle基于settings.Gradle文件指定哪个子项目初始化每个子项目的项目对象。

由于有很多项目配置,因此我们将简要介绍常见的配置共享和配置独占。

3.多模块项目的Gradle目录结构

示例:我的示例项目demo,我需要有一个common模块用于公用代码,一个rest模块用于提供rest接口,rest依赖common,如果用gradle构建,目录树会是这样:

demo
├── build.gradle   -- 全局配置
├── settings.gradle  -- 全局配置
├── common      -- 子模块1目录
│  └── build.gradle -- 子模块1配置
├── rest       -- 子模块2配置
│  └── build.gradle -- 子模块2配置
...

“所有项目”属性。 返回这个项目对象及其所有子项目。

subProjects属性。 返回这个项目的所有子项目。

项目’ : su B-project-name ’ )来设置相应子项目的配置。

configure(subprojects.findall ) it.name.contains(‘XXX’ )会来寻找符合您需求的子专案。

将您自己的配置添加到子项目的build.gradle文件中。

关于 本文的代码,和技术问题, 请来尼恩 发起的Java 高并发 疯狂创客圈 社群交流

Gradle项目管理工具

基于Groovy的特定领域语言来声明项目设置

Gradle安装(Windows)

1.下载解压版

  • 版本列表:https://services.gradle.org/distributions/
  • v6.5:https://downloads.gradle-dn.com/distributions/gradle-6.5-bin.zip**(用迅雷下载可能会快些)**

2.配置环境变量

  1. gradle_home
    • 变量名:GRADLE_HOME
    • 变量值:D:\\tool\\gradle-7.5.1-all\\gradle-7.5.1(gradle安装目录)
  2. path(编辑)
    • 变量名:Path(编辑)
    • 变量值:%GRADLE_HOME%\\bin(增加)
  3. gradle_user_home(在远程仓库下载的jar包保存到该路径下)
    • 变量名:GRADLE_USER_HOME
    • 变量值:D:\\dev\\maven\\repository
D:\\dev\\jdk\\java-1.8.0-openjdk-1.8.0.312-2.b07.dev.redhat.windows.x86_64

D:\\tool\\Java\\jdk-11.0.6

3.配置init.gradle

gradle安装目录\\init.d目录下,创建init.gradle文件,

allprojects
    repositories 
        def REPOSITORY_URL = 'https://maven.aliyun.com/nexus/content/groups/public/'
        all  ArtifactRepository repo ->
            def url = repo.url.toString()
            if ((repo instanceof MavenArtifactRepository) && (url.startsWith('https://repo1.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com'))) 
                project.logger.lifecycle 'Repository $repo.url replaced by $REPOSITORY_URL .'
                remove repo
            
        
        maven 
            url REPOSITORY_URL
        
    


    buildscript 
        repositories 
            def REPOSITORY_URL = 'https://maven.aliyun.com/nexus/content/groups/public/'
            all  ArtifactRepository repo ->
                def url = repo.url.toString()
                if ((repo instanceof MavenArtifactRepository) && (url.startsWith('https://repo1.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com'))) 
                    project.logger.lifecycle 'Repository $repo.url replaced by $REPOSITORY_URL .'
                    remove repo
                
            
            maven 
                url REPOSITORY_URL
            
        
    


初始化基本配置:配置远程仓库地址(gradle没有自己的仓库,使用的是maven的仓库)

4.验证是否配置成功

cmd输入命令:

gradle -v

关于 本文的代码,和技术问题, 请来尼恩 发起的Java 高并发 疯狂创客圈 社群交流

Gradle本地仓库

可能有很多人在纠结这个 Gradle 能不能像 maven 一样手动修改本地仓库,答案当然是肯定的,

而且很简单,只需要在环境变量里面做个配置即可如下图:

即添加一个名称为 GRADLE_USER_HOME ,值是你想放gradle仓库的地方即可。

GRADLE_HOME=D:\\tool\\gradle-7.5.1-all\\gradle-7.5.1

GRADLE_USER_HOME= D:\\dev\\maven\\repository

GRADLE_USER_HOME= D:\\dev\\maven\\graddleRep

spring-boot-dependencies.version = 2.1.12.RELEASE

 //先从本地仓库寻找,本地仓库没有再从中央仓库寻找
    mavenLocal();
    

关于 本文的代码,和技术问题, 请来尼恩 发起的Java 高并发 疯狂创客圈 社群交流 ,

Gradle Java 构建入门

Java 插件

如你所见,Gradle 是一个通用工具。它可以通过脚本构建任何你想要实现的东西,真正实现开箱即用。

但前提是你需要在脚本中编写好代码才行。

大部分 Java 项目基本流程都是相似的:编译源文件,进行单元测试,创建 jar 包。

使用 Gradle 做这些工作不必为每个工程都编写代码。

Gradle 已经提供了完美的插件来解决这些问题。

插件就是 Gradle 的扩展,简而言之就是为你添加一些非常有用的默认配置。

Gradle 自带了很多插件,并且你也可以很容易的编写和分享自己的插件。

Java plugin 作为其中之一,为你提供了诸如编译,测试,打包等一些功能。

Java 插件为工程定义了许多默认值,如Java源文件位置。

如果你遵循这些默认规则,那么你无需在你的脚本文件中书写太多代码。

当然,Gradle 也允许你自定义项目中的一些规则,实际上,由于对 Java 工程的构建是基于插件的,那么你也可以完全不用插件自己编写代码来进行构建。

后面的章节我们通过许多深入的例子介绍了如何使用 Java 插件来进行以来管理和多项目构建等。但在这个章节我们需要先了解 Java 插件的基本用法。

一个基本 Java 项目

来看一下下面这个小例子,想用 Java 插件,只需增加如下代码到你的脚本里。

采用 Java 插件

build.gradle

plugins 
    id 'org.springframework.boot' version '2.4.3'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'


定义一个 Java 项目只需如此而已。

这将会为你添加 Java 插件及其一些内置任务。

添加了哪些任务?

你可以运行 gradle tasks 列出任务列表。这样便可以看到 Java 插件为你添加了哪些任务。

标准目录结构如下:

------------------------------------------------------------
Tasks runnable from root project 'demo'
------------------------------------------------------------

Application tasks
-----------------
bootRun - Runs this project as a Spring Boot application.

Build tasks
-----------
assemble - Assembles the outputs of this project.
bootBuildImage - Builds an OCI image of the application using the output of the bootJar task
bootJar - Assembles an executable jar archive containing the main classes and their dependencies.
bootJarMainClassName - Resolves the name of the application's main class for the bootJar task.
bootRunMainClassName - Resolves the name of the application's main class for the bootRun task.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles main classes.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes.
testClasses - Assembles test classes.

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.

Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the main source code.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'demo'.
dependencies - Displays all dependencies declared in root project 'demo'.
dependencyInsight - Displays the insight into a specific dependency in root project 'demo'.
dependencyManagement - Displays the dependency management declared in root project 'demo'.
help - Displays a help message.
javaToolchains - Displays the detected java toolchains.
outgoingVariants - Displays the outgoing variants of root project 'demo'.
projects - Displays the sub-projects of root project 'demo'.
properties - Displays the properties of root project 'demo'.
resolvableConfigurations - Displays the configurations that can be resolved in root project 'demo'.
tasks - Displays the tasks runnable from root project 'demo' (some of the displayed tasks may belong to subprojects).


To see more detail about a task, run gradle help --task <task>


Gradle 默认会从 src/main/java 搜寻打包源码,在 src/test/java 下搜寻测试源码。

并且 src/main/resources 下的所有文件按都会被打包,所有 src/test/resources 下的文件 都会被添加到类路径用以执行测试。

所有文件都输出到 build 下,打包的文件输出到 build/libs 下。

Java 插件的众多任务

Java 插件为你添加了众多任务。

但是它们只是在你需要构建项目的时候才能发挥作用。

最常用的就是 build 任务,这会构建整个项目。

当你执行 gradle build 时,Gralde 会编译并执行单元测试,并且将 src/main/* 下面 class 和资源文件打包。

构建 Java 项目

运行 gradle build 的输出结果

21:03:18: Executing 'build'...


> Configure project :
crazy maker circle!
 a good circle
myValue

> Task :service:compileJava
> Task :service:processResources NO-SOURCE
> Task :service:classes
> Task :service:jar
> Task :app:compileJava
> Task :app:processResources NO-SOURCE
> Task :app:classes
> Task :app:bootJarMainClassName
> Task :app:bootJar
> Task :app:jar SKIPPED
> Task :app:assemble
> Task :app:compileTestJava
> Task :app:processTestResources NO-SOURCE
> Task :app:testClasses

> Task :app:test
2022-11-21 21:03:26.985  INFO 44316 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'

> Task :app:check
> Task :app:build

BUILD SUCCESSFUL in 8s
7 actionable tasks: 7 executed
21:03:27: Execution finished 'build'.

关于 本文的代码,和技术问题, 请来尼恩 发起的Java 高并发 疯狂创客圈 社群交流

其余一些较常用的任务有如下几个:

clean

删除 build 目录以及所有构建完成的文件。

assemble

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

check

编译并测试代码。一些其他插件也可能会增强这个任务的功能。例如,如果采用了 Code-quality 插件,这个任务会额外执行 Checkstyle。

发布 jar 包

如何发布 jar 包?你需要告诉 Gradle 发布到到哪。

在 Gradle 中 jar 包通常被发布到某个仓库中。在下面的例子中,我们会将 jar 包发布到本地目录。当然你也可以发布到远程仓库或多个远程仓库中。

发布 jar 包

build.gradle

uploadArchives 
    repositories 
       flatDir 
           dirs 'repos'
       
    

执行 gradle uploadArchives 以发布 jar 包。

类似Maven的dependencyManagement方式实现依赖管理

Spring开发了一个类似Maven的依赖关系管理功能的Gradle插件( )。

引入插件

plugins 
  id "io.spring.dependency-management" version "1.0.8.RELEASE"


依赖管理配置

你有两个选项来配置依赖项管理:

  1. 使用插件的DSL来直接配置依赖项
  2. 导入一个或者多个已经存在的Maven bom文件

依赖项的管理默认被, 应用到所有的配置或者一个或者多个指定的配置中。

依赖项管理DSL

使用:分隔符的配置方式:

dependencyManagement 
    dependencies 
        dependency 'org.springframework:spring-core:4.0.3.RELEASE'
    


通过groupnameversion进行指定配置:

dependencyManagement 
    dependencies 
        dependency group:'org.springframework', name:'spring-core', version:'4.0.3.RELEASE'
    


通过上面两种方式中的任意一种进行了管理配置之后,在需要引入spring-core的包时,就可以通过如下方式配置依赖:

dependencies 
    compile 'org.springframework:spring-core'


这样一个依赖管理配置就完成了。

依赖集配置

如果对于多个模块具有相同的group和version的依赖配置,你可以使用依赖集进行配置。

这样你就只需要指定统一的group和version,而依赖模块不需要再额外指定。

如下所示:

dependencyManagement 
     dependencies 
          dependencySet(group:'org.slf4j', version: '1.7.7') 
               entry 'slf4j-api'
               entry 'slf4j-simple'
          
     


排除依赖(exclusion)

可以使用Maven的Exclusios语义进行依赖项的排除。
对单个依赖项进行排除:

dependencyManagement 
    dependencies 
        dependency('org.springframework:spring-core:4.0.3.RELEASE') 
            exclude 'commons-logging:commons-logging'
        
    


也可以对依赖集的entry中进行排除:

dependencyManagement 
    dependencies 
        dependencySet(group:'org.springframework', version: '4.1.4.RELEASE') 
            entry('spring-core') 
                exclude group: 'commons-logging', name: 'commons-logging'
            
        
    


导入Maven Bom

插件允许你导入已经存在的Maven Bom来使用其依赖的关系管理:

dependencyManagement 
     imports 
          mavenBom 'io.spring.platform:platform-bom:1.0.1.RELEASE'
     


dependencies 
     compile 'org.springframework.integration:spring-integration-core'


这个配置会将Spring框架的Bom的依赖应用到当前的项目

本地Module library依赖

//module需要在项目根目录下的settings.gradle中通过include引入
implementation project(':librarydict')

2.本地二进制library依赖:jar和aar

本地的jar和aar需要放在module的libs文件夹下,通过这种方式依赖的弊端时不知道jar和aar的版本号,如果要按照这种方式依赖,建议将jar/aar的名字加上版本信息,方便确认版本
依赖jar:
//可以一条依赖引入libs下所有的jar
implementation fileTree(dir:'libs',include:['*.jar'])

//也可以指定依赖某一个或几个jar
implementation files('libs/dict-v120.jar','libs/download-v151.jar') 

引入远程maven仓库

//依赖明确的版本,标明group、name和version
implementation group:'con.android.demo',name:'library-dict',version:'1.2.0'

//通常按照如下方式简写即可
implementation 'com.android.demo:library-dict:1.2.0'

//也可以不知道版本,将version改为"+",当远程仓库有更新的版本后,构建时会拉取最新的版本。
//好处是可以始终依赖最新的library:弊端是有可能library的改动导致编译不过或者功能变更不稳定,因为每次都需要检查是否有最新版本,所以构建效率会低一些
implementation 'com.android.demo:library-dict:+'

修改gradle的镜像仓库

改单个项目

在项目的build.gradle文件中,修改repositories配置,

将mavenCentral()改为 maven url ‘http://maven.aliyun.com/nexus/content/groups/public/’, 如:

repositories 
    maven  url 'http://maven.aliyun.com/nexus/content/groups/public/' 

更改所有项目

如果想一次更改所有的仓库地址,可以在 USER_HOME/.gradle/文件夹下

添加 init.gradle 文件来配置,如:

allprojects
    repositories 
        def REPOSITORY_URL = 'http://maven.aliyun.com/nexus/content/groups/public/'
        all  ArtifactRepository repo ->
            if(repo instanceof MavenArtifactRepository)
                def url = repo.url.toString()
                if (url.startsWith('https://repo1.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com/')) 
                    remove repo
                
            
        
        maven 
            url REPOSITORY_URL
        
    

修改Gradle本地仓库的位置 方法

Gradle的配置
可能有很多人在纠结这个 Gradle 能不能像 maven 一样手动修改本地仓库,答案当然是肯定的,而且很简单,只需要在环境变量里面做个配置即可。

即添加一个名称为 GRADLE_USER_HOME ,值是你想放gradle仓库的地方即可。

  1. 新建系统变量:
GRADLE_USER_HOME
D:\\gradle\\.gradle\\

2.如下图:

补充说明一点 据说 Gradle有个 Daemon配置,开启这个配置能有效的提高编译速度,具体是不是这样我没有做过对比因为我安装了gradle后就配置了。。。

3.具体操作如下:

在咱们的gradle仓库.gradle目录下创建一个gradle.properties 文件 ,再打开该文件在其中添加如下语句保存即可:

org.gradle.daemon=true  

就这样简单。

Gradle工程目录

gradle-demo
|---src
|---|---main
|---|---|---java(放置正式代码目录)
|---|---|---resources(放置正式配置文件目录)
|---|---|---webapp(放置页面元素)
|---|---test
|---|---|---java(放置单元测试代码目录)
|---|---|---resources(放置测试配置文件目录)
|---build.gradle
|---settings.gradle

关于 本文的代码,和技术问题, 请来尼恩 发起的Java 高并发 疯狂创客圈 社群交流 ,

groovy编程语言

Gradle在idea中使用

  1. idea中,使用groovy语言编辑器,

    Tools - Groovy Console

  2. 方法调用,省略分号,小括号

  3. 定义字符串,单引号定义普通字符串,双引号可以引用变量,三引号按格式定义字符串

输出

//介绍groovy编程语言
println("hello groovy"); // idea快捷键sout
println("hello groovy") // 可以省略最后的分号
println "hello groovy" // 可以省略括号
println 12 + ":" + 24

println 12 + 24

关于 本文的代码,和技术问题, 请来尼恩 发起的Java 高并发 疯狂创客圈 社群交流

定义变量

// groovy 中定义变量
// def 是弱类型,groovy会自动根据情况来给变量赋予对应的类型
def foo = 18;
def bar = 疯狂创客圈 
println foo;


字符串定义

方式1:单引号定义字符串

使用 '...' 单引号来定义字符串,这种定义的字符串跟 Java 中定义的字符串是一样的,都是不可变的。

并且通过 str1.class 可以验证方式1输出的字符串类型就是 java.lang.String

方式2:双引号定义字符串

使用 "..." 双引号来定义字符串,这种定义的字符串跟 Java 中定义的字符串是一样的,都是不可变的。

并且通过 str1.class 可以验证方式2输出的字符串类型就是 java.lang.String


str1 = '疯狂创客圈'  // 定义普通字符串
str2 = "name:$str1" //可以引用变量
str3 = '''name:xiaoming
age:18'''  //按格式定义字符串
println str1
println str1.class
println str2
println str2.class //class org.codehaus.groovy.runtime.GStringImpl


通过上面的例子可以看出,通过在str2中拼接 $变量/表达式 之后输出的 class 类型不再是 java.lang.String 而是 org.codehaus.groovy.runtime.GStringImpl

很明显这个类型就是 GString 的实现类。

因此可以知道单引号和双引号定义的字符串的区别在双引号定义的字符串可以通过 $ 进行扩展,而单引号定义的字符串是不可变的,因此不可以扩展。

方式3:三个单引号定义字符串

使用 '''...''' 双引号来定义字符串,这种定义的字符串跟 Java 中定义的字符串是一样的,都是不可变的。

并且通过 str3.class 可以验证方式3输出的字符串类型就是 java.lang.String

str1 = '疯狂创客圈'  // 定义普通字符串


//这里会有一个换行符号\\n
def str5 ='''
疯狂创客圈  一个java 高并发研究社群
Hello  疯狂创客圈
    疯狂创客圈
    
$str1 是一个java 高并发研究社群
'''
println str5.class //class org.codehaus.groovy.runtime.GStringImpl

assert  str5.startsWith("\\n")//验证 str5 是以 \\n 开头的

方式3对字符串的样式进行修改,例如换行,缩进。

关于 本文的代码,和技术问题, 请来尼恩 发起的Java 高并发 疯狂创客圈 社群交流

方式4:三个双引号定义字符串

str1 = '疯狂创客圈'  // 定义普通字符串


//这里会有一个换行符号\\n
def str5 ="""
疯狂创客圈  一个java 高并发研究社群
Hello  疯狂创客圈
    疯狂创客圈
    
$str1 是一个java 高并发研究社群
"""

println str5
println str5.class //class org.codehaus.groovy.runtime.GStringImpl

assert  str5.startsWith("\\n")//验证 str5 是以 \\n 开头的

关于 本文的代码,和技术问题, 请来尼恩 发起的Java 高并发 疯狂创客圈 社群交流

定义一个集合类型



def list = ['a','b']
// 往list中添加元素
list.add("疯狂创客圈")
list.add("java高并发社群")
list << 'c'
// 取出list中第3个元素
println list.get(2)


定义一个map


def map = ['key1':'value1','key2':'value2']
// 向map中添加键值对
map.key3 = 'value3'
// 打印出key3的值
println map.get('key3')

闭包(无参数)

// groovy 中的闭包
// 什么是闭包?闭包其实就是一段代码块。在gradle中,我们主要是把闭包当参数来使用
// 闭包省略()
//plugins(
//    id('java')
//)
//相当于
//plugins 
//    id 'java'
//

// 定义一个闭包
def b1 = 
    println "hello b1"

// 定义一个方法,方法里面需要闭包类型的参数
def method1(Closure closure) 
    //closure()
    closure.call()

// 调用方法method1
method1(b1)
method1 b1

method1(
    println "xiaoming"
)

method1 
    println "xiaoming"


闭包(有参数)

//定义一个闭包,带参数
def b2 = 
    v ->
        println "hello $v"

// 定义一个方法,方法里面需要闭包类型的参数
def method2(Closure closure)
    //closure("xiaoma")
    closure.call("xiaoma")

// 调用方法method2
method2 b2
method2 
    v ->
        println "hello $v"


断言 assert

where = 疯狂创客圈
assert where == 疯狂创客圈

关于 本文的代码,和技术问题, 请来尼恩 发起的Java 高并发 疯狂创客圈 社群交流

gradle构建脚本介绍

gradle构建脚本介绍(build.gradle)
两个重要的概念 project 和 task
任何一个Gradle构建都由一个或多个project组成,每个project包括许多的构建部分
每个project由一个或多个Task组成,每个Task表示在构建执行过程中的一个原子操作
构建Project完成后会生成一个jar或者war文件,构建过程中Gradle基于build.gradle实例化一个org.gradle.api.Project对象,并通过project变量来隐式的调用其成员变量
Project对象属性:project(隐式使用)、group、name、version、path、description、projectDir、buildDir、ant
其它常用配置:plugins(apply plugin)、dependencies、repositories、task、ext(gradle.properties 属性配置)

Gradle管理jar包

build.gradle文件的基本内容

plugins 
    id 'java'
    // web工程需要的插件
    id 'war'


version '1.0-SNAPSHOT'
group 'xin.yangshuai'

sourceCompatibility = 1.8

/*
 * 指定所使用的仓库
 */
repositories 
    // Gradle没有自己的中央仓库
    // 先从本地maven仓库寻找依赖的jar包,存在则直接使用本地maven仓库的jar
    mavenLocal()
    // 本地maven仓库没有则从远程仓库下载jar包,并保存到 环境变量GRADLE_USER_HOME 配置的路径下
    // 设置maven仓库阿里镜像地址
    maven  url 'http://maven.aliyun.com/nexus/content/groups/public/' 
    // 配置使用Maven的中央仓库
    mavenCentral()


/**
 * 配置依赖的jar包
 */
dependencies 
    testCompile group: 'junit', name: 'junit', version: '4.12'
    /* web工程需要的jar包 */
    compile group: 'org.springframework', name: 'spring-context', version: '5.0.2.RELEASE'
    compile group: 'org.springframework', name: 'spring-web', version: '5.0.2.RELEASE'
    compile group: 'org.springframework', name: 'spring-webmvc', version: '5.0.2.RELEASE'
    providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1'
    providedCompile group: 'javax.servlet', name: 'jsp-api', version: '2.0'


配置gradle的repositories仓库

mavenLocal()的配置

  1. mavenLocal()表示使用本地maven仓库
  2. mavenCentral()使用maven中心仓库
  3. 使用阿里云(maven url ‘http://maven.aliyun.com/nexus/content/groups/public/’)#这个相当于使用自定义maven仓库地址的配置,可以是私服。
  4. JCenter是Goovy Grape内的默认仓库,Gradle内建支持jcenter()仓库,项目库打包成aar文件类似jar,只是多了res,lib文件的包,上传到jcenter后,可以很方面的在本地调用库文件
repositories 


    mavenLocal()
//        mavenCentral()

    maven url 'https://maven.aliyun.com/repository/public/';


    maven  url 'https://maven.aliyun.com/repository/jcenter' 
    maven  url 'https://maven.aliyun.com/repository/google' 
    maven  url 'https://maven.aliyun.com/repository/central' 
    maven  url 'https://maven.aliyun.com/repository/gradle-plugin' 


gradle默认本地依赖存储位置

因为Gradle如果不配置环境变量,则会在用户目录下(在Windows下是C盘的目录)创建.gradle目录,并将下载的依赖文件保存在这个目录里。

如果不想使用缺省目录,则可以设置环境变量GRADLE_USER_HOME的路径,就可改变gradle的缓存目录。

使用maven本地仓库


#配置M2_HOME
#mavenLocal() 时Gradle默认会按以下顺序去查找本地的maven仓库:
#  USER_HOME/.m2/settings.xml  > M2_HOME/conf/settings.xml >  USER_HOME/.m2/repository。


  1. 修改build.gradle文件,配置maven本地仓库mavenLocal()
repositories 
    mavenLocal()


  1. 使用maven本地仓库,需要告知gradle本地maven仓库的地址,配置

    M2_HOME
    

    环境变量,

    M2_HOME   /conf/settings.xml
    

    中指定我们本地仓库的位置

    • 变量名:M2_HOME
    • 变量值:D:\\tool\\apache-maven-3.6.0(maven安装路径)

当我们使用maven本地仓库(mavenLocal())时,jar包会直接利用本地maven仓库,而不会去下载

**参考:**https://blog.csdn.net/yzpbright/article/details/89001633?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase

注意: gradle寻找本地maven仓库位置的策略

USER_HOME  /.m2/settings.xml` >> `M2_HOME/conf/settings.xml` >> `USER_HOME/.m2/repository

1、我们一般在maven的安装目录/conf/settings.xml(也就是我们配置的maven环境变量)中配置本地仓库位置,所以我们需要让gradle选择该路径,从而使用我们配置的maven本地仓库

2、gradle先寻找USER_HOME/.m2/settings.xml,所以我们要删掉该文件(其实也可以将安装目录下的settings.xml复制过来)

3、maven环境变量我们习惯配置成MAVEN_HOME,但是gradle寻找的是M2_HOME,所以我们需要配置M2_HOME环境变量

验证: 切换使用mavenCentral()和mavenLocal(),查看jar包引用地址

使用远程仓库

  1. 修改build.gradle文件,配置maven中央仓库
repositories 
    mavenCentral()


  1. 当需要在远程仓库下载jar包时,会将jar包保存到GRADLE_USER_HOME\\caches\\modules-2\\files-2.1\\文件夹下,配置 GRADLE_USER_HOME 环境变量,也可以直接在idea中指定位置
    • 变量名:GRADLE_USER_HOME
    • 变量值:D:\\work\\gradleCK

其它可用的远程仓库地址

repositories 
    mavenLocal()
    // 阿里
    maven  url 'http://maven.aliyun.com/nexus/content/groups/public/' 
    mavenCentral()


关于gradle中jar包引用的说明

如果我们在repositories中先配置mavenLocal()(maven本地仓库),再配置mavenCentral()(远程仓库)

那么gradle引用jar的位置就会出现两个,如果本地maven仓库中存在则直接引用本地maven仓库中的jar包

如果本地maven仓库中不存在,则会连接远程仓库地址,将jar包下载到gradle本地缓存地址,并且引用该地址下的jar包。

注意: gradle并不会向本地maven仓库中下载jar包,gradle缓存路径下的jar包与maven本地仓库中的jar包的格式也有区别。

**参考:**https://blog.csdn.net/feinifi/article/details/81458639

验证: 查看项目中不同jar包的引用地址(maven仓库中存在的jar包和不存在的jar包,观看其引用的地址)

gradle中jar包的依赖配置

jar包依赖方式

/**
 * 配置依赖的jar包
 * gradle工程所有的jar包的坐标都在dependencies属性内放置
 * 每一个jar包的坐标都有三个基本元素组成 group,name,version
 * 添加坐标的时候都要带上jar包的作用域
 */
dependencies 
    testCompile group: 'junit', name: 'junit', version: '4.12'


jar包的依赖范围(作用域)

jar包的依赖范围(作用域):
compile:编译阶段:主程序、测试程序均有效;运行阶段:均有效
providedCompile:编译阶段:主程序、测试程序均有效;运行阶段:均无效(依靠运行时环境提供的jar包)
runtime:编译阶段:主程序、测试程序均无效(无需依赖);运行阶段:均有效
testCompile:编译阶段:主程序无效,测试程序有效;运行阶段:均有效
testRuntime:编译阶段:主程序、测试程序均无效(无需依赖);运行阶段:测试程序有效

jar包依赖版本冲突默认解决方式

jar包依赖具有传递性
依赖jar包版本存在冲突解决方案:
maven:最短路径原则,先声明原则
gradle:选择最高版本

修改jar包依赖的配置策略

configurations.all 
    resolutionStrategy 
        // 配置后将不自动处理jar包版本冲突,可以与依赖的排除配合使用
        failOnVersionConflict()
        // 强制使用某个版本的jar包,覆盖依照gradle默认策略引用的jar包
        force 'org.slf4j:slf4j-api:1.7.24'
    


直接在build.gradle中配置configurations.all

依赖的排除

dependencies redis 集群 实操 (史上最全5w字长文)

redis 集群 实操 (史上最全5w字长文)

Netty内存池 (5w长文+史上最全)

面经 | 史上最全 Java 多线程面试题及答案

可能是史上最全面的内存管理文章

这指南我可以用10年!史上最全Linux系统安全强化指南(最强干货,建议收藏!)