IDEA+Gradle项目配置


IDEA项目配置

IDEA默认集成了Gradle插件,项目创建后会自动创建$USER_HOME/.gradle目录,用于存放gradle配置及依赖包文件;

Gradle源地址配置

Gradle根据依赖信息从源地址下载依赖包,默认镜像源为国外源地址,下载速度较慢;实际开发时可修改全局配置,将镜像源指向国内源地址,对所有gradle项目均生效;

Gradle全局源配置

${USER_HOME}/.gradle/目录下新建init.gradle文件,添加以下内容:

def repoConfig = {
    all { ArtifactRepository repo ->
        if (repo instanceof MavenArtifactRepository) {
            def url = repo.url.toString()
            if (url.contains('maven.apache') || url.contains('maven.org') || url.contains('jcenter.bintray')) {
                remove repo
            }
        }
    }
    maven { url 'https://maven.aliyun.com/repository/central' }
    maven { url 'https://maven.aliyun.com/repository/jcenter' }
    maven { url 'https://maven.aliyun.com/repository/google' }
    maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
}

//项目依赖包源配置
allprojects {
  
  	//gradle脚本依赖源信息
    buildscript {
        repositories repoConfig
    }

    repositories repoConfig
}

Gradle项目配置

Gradle项目创建时,会自动生成配置信息:

  • build.gradle,主要用于配置插件、源地址、依赖包以及自定义任务;
    • plugins:新版DSL配置插件信息;
    • apply plugin:老版配置插件信息;
    • repositories:配置依赖源地址;
    • dependencies:配置依赖包信息;
  • settings.gradle,主要定义项目和模块依赖信息;
    • rootProject.name:配置项目名称;
    • include:配置子模块名称
  • xxx.gradle:自定义配置文件,主要用于定义自定义task或变量;
  • gradle.properties:用于定义属性信息;主要用于配置项目或模块属性,格式为KV;
// build.gradle配置文件

plugins {
    id "com.github.johnrengelman.shadow" version "7.0.0"
}

allprojects {
    apply from: rootProject.getRootDir().getAbsolutePath() + "/func.gradle"
    apply plugin: 'java-library'
    apply plugin: 'eclipse'
    apply plugin: 'com.github.johnrengelman.shadow'


    //download dependcies jar source code
    eclipse {
        classpath {
            downloadSources=true
            downloadJavadoc = true
        }
    }

    group 'org.semon'
    version 'v1.0'

    repositories {
        mavenCentral()
    }

    dependencies {
      	//slf4j核心依赖
        implementation 'org.slf4j:slf4j-api:1.7.32'
      	//slf4j实现类,声明slf4j使用log4j2日志
        implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.14.1'
				
      	//log4j2核心包
        implementation 'org.apache.logging.log4j:log4j-core:2.14.1'
        implementation 'org.apache.logging.log4j:log4j-api:2.14.1'
      	
     		//lombok效率包
        compileOnly 'org.projectlombok:lombok:1.18.20'
      	//junit测试包
        compileOnly 'junit:junit:4.13.2'
    }
  
  	def projectName = 'CodeSediment'
    def v_baseName = 'demo'
    def v_classifier = 'dev'
    def v_version = 'v1.0'
    def v_className = 'org.semon.Main'

		//parse project properties
    task parseProp {
        projectName = project.name.toString()
        v_baseName = project.properties[projectName+'.v_baseName']
        v_classifier = project.properties[projectName+'.v_classifier']
        v_version = project.properties[projectName + '.v_version']
        v_className = project.properties[projectName + '.v_className']
    }

    shadowJar {
        archiveBaseName = v_baseName
        archiveClassifier = v_classifier
        archiveVersion = v_version
        manifest {
            attributes('Main-Class': v_className)
        }

        //exclude properties file
        exclude('system.properties')

        //exclude specified jar
        dependencies {
            exclude(dependency('org.mongodb:mongo-java-driver:3.3.0'))
        }

        //include build.gradle
        from("./") {
            include 'build.gradle'
        }

        // fix pack file more than 65535 files
        zip64 true
    }

    shadowJar.dependsOn("parseProp")

    task packJar (dependsOn: ['clean','shadowJar'])


    jar {
        manifest {
            attributes "Main-Class": v_className
        }

        from {
            configurations.compileClasspath.collect{ it.isDirectory()? it : zipTree(it)}
        }

    }
}

// settings.gradle  
rootProject.name = 'CodeSediment'
include '01-utils'

// gradle.properties
archBaseName = utils
01-utils.v_baseName = utils
01-utils.v_classifier = release
01-utils.v_version = v1.0
01-utils.v_className= org.demo.FileUtils


//func.gradle


def projectName = 'CodeSediment'
def v_baseName = 'demo'
def v_classifier = 'dev'
def v_version = 'v1.0'
def v_className = 'org.semon.Main'

//parse project properties
task parseProp {
  projectName = project.name.toString()
  v_baseName = project.properties[projectName+'.v_baseName']
  v_classifier = project.properties[projectName+'.v_classifier']
  v_version = project.properties[projectName + '.v_version']
  v_className = project.properties[projectName + '.v_className']
}

shadowJar {
  archiveBaseName = v_baseName
  archiveClassifier = v_classifier
  archiveVersion = v_version
  manifest {
    attributes('Main-Class': v_className)
  }

  //exclude properties file
  exclude('system.properties')

  //exclude specified jar
  dependencies {
    exclude(dependency('org.mongodb:mongo-java-driver:3.3.0'))
  }

  //include build.gradle
  from("./") {
    include 'build.gradle'
  }

  // fix pack file more than 65535 files
  zip64 true
}

shadowJar.dependsOn("parseProp")

task packJar (dependsOn: ['clean','shadowJar'])


jar {
        manifest {
            attributes "Main-Class": v_className
        }

        from {
            configurations.compileClasspath.collect{ it.isDirectory()? it : zipTree(it)}
        }

    }


task showProp {
    println  project.property(archBaseName)
}


task showProps {
    println project.properties.each {
        println "properties: ${it.key} --> ${it.value}"
    }
}


task showRepos {
    repositories.each {
        println "repository: ${it.url}"
    }
}


// 示例任务
task copyDemo(type: Copy) {
    from('sourceSets/')
    into('/build')
}

task zipDemo(type: Zip) {
    from('/build')
    destinationDirectory = file('target/libs')
    archiveBaseName = 'org.demo'
    archiveAppendix = 'root'
    archiveVersion = 'v1.0'
}

task tarDemo(type: Tar) {
    from('build')
    archiveBaseName = 'org.semon'
    destinationDirectory = file('target/libs')
    archiveClassifier = 'release'
    archiveVersion = 'v1.0'
    compression = 'GZIP'
}

task execDemo(type: Exec) {
    executable 'ls'
    args('-l', workingDir)
}

task syncDemo(type: Sync) {
    from('target/libs')
    into('build')
    preserve {
        include('extraDir/*')
        include('dir1/*')
        exclude('dir2/a.txt')
    }
}

Gradle构建生命周期

Gradle的构建过程有着固定的生命周期,分别为:

  1. 初始化阶段
  2. 配置阶段
  3. 执行阶段

初始化阶段

初始化阶段主要任务是:创建项目的层次结构,并为每个项目创建一个Project实例对象;

在初始化阶段,会执行settings.gradle脚本,并读取其中的include信息,进而为每一个模块(build.gradle文件)创建一个与之对应的Project对象,最终形成一个项目的层次结构;

配置阶段

配置阶段的任务是:执行各项目下的build.gradle脚本,完成Project配置,并构造Task任务依赖关系图以便在执行阶段按照依赖关系执行Task;

配置阶段代码执行

配置阶段是我们最长接触到的构建阶段,比如应用外部构建插件apply plugin: java等;

每个build.gradle脚本文件对应一个Project对象,在初始化阶段创建;配置阶段执行的代码包括:

  • build.gradle中的各种语句
  • 闭包
  • Task中的配置段语句

执行任何Gradle命令,在初始化阶段和配置阶段的代码都会被执行;

Task中除了Action外的代码段都在配置阶段执行;(属性配置,语句打印等都会在配置阶段执行)

Task依赖关系配置

配置阶段另外一个重要的任务就是构建Task依赖关系的有向无环图,简单的说,就是给所有的Task安排一个执行顺序,在执行阶段,就按照这个顺序执行所有的Task任务;

执行阶段

执行阶段就是根据配置阶段构建的Task依赖关系去执行相关的Task;

当我们运行项目的时候,Gradle就会根据Task的依赖关系依次去执行相关的Task,还可以通过Gradle命令去执行指定的Task,例如:./gradlew shadowJar

Gradle-Task执行顺序配置

在Gradle中,有三种方式指定Task的执行顺序:

  1. dependsOn强依赖方式
  2. 通过Task输入输出
  3. 通过API指定执行顺序

通过dependsOn强依赖方式指定

dependsOn强依赖的方式可以分为静态依赖动态依赖

  • 静态依赖:在创建Task时,就明确知道定义的Task需要依赖的Task是什么,直接通过dependsOn参数或者dependsOn方法指定所依赖的Task;

    Task提供了dependsOnfinalizedBy方法来管理Task之间的依赖关系,依赖关系表达的是执行这个Task时所需要依赖的其他Task,也就是说这个Task不能被单独执行,执行这个Task之前或之后执行另外的Task;

  • 动态依赖:在创建Task时,不知道需要依赖哪些Task,通过dependsOn方法动态依赖符合条件的Task;

task taskX {
  doLast{
    println 'taskX'
  }
}

task taskY {
  doLast {
    println 'taskY'
  }
}

// 静态依赖1
task taskZ (dependsOn: taskX) {
  doLast {
    println 'taskZ'
  }
}
// 静态依赖2
taskZ.dependsOn(taskY)

//动态依赖

task taskA {
  dependsOn this.tasks.findAll {
    task -> return task.name.startsWidth('lib')
  }
  doLast{
    println 'taskA'
  }
}

通过Task输入输出制定

当一个参数作为TaskA的输出参数,同时又作为TaskB的输入参数,那么当执行当执行TaskB的时候要先执行TaskA,即输出的Task要先于输入的Task执行;

ext {
  demoFile = file("${this.buildDir}/demo.txt")
} 

task producer {
  outputs.file demoFile
  doLast {
    outputs.getFiles().singleFile.withWriter {
      writer -> writer.append("hello world")
    }
    
    println 'producer Task end.'
  }
}


task consumer {
  inputs.file demoFile
  doLast {
    println "read file: ${inputs.file.singleFile.text}"
    println "consumer Task end." 
  }
}

task demo(dependsOn: [producer,consumer]) {
  doLast {
    println "demo end;"
  }
}

demoFile是procuder的输出参数,是consumer的输入参数,所以producer咸鱼consumer执行;

通过API制定执行顺序

  • mustRunAfter:指定必须在哪个Task执行完成之后在执行,如taskA.mustRunAfter(taskB),即taskA必须在taskB之后执行;
  • finalizedBy:在任务结束之后执行指定的Task;如taskA.finalizedBy(taskB),即taskA执行结束之后再执行taskB;

Gradle打印Task依赖关系

//应用插件
apply plugin: 'com.dorongold.gradle.tasktree.TaskTreePlugin'

//查看依赖关系
./gradlew taskName taskTree --no-repeat

Gradle插件

Gradle添加支持两种语法方式:

  • apply plugin: java:老版本添加插件方式,
  • plugins { id 'java' }:新版本添加插件方式,支持DSL领域语法;

java插件

一般Java项目,默认会添加java插件,但建议使用java-library,添加java插件后,默认支持Jar任务,可对用户代码及依赖架包进行打包;但无法实现对依赖包源码进行打包;

  • java-library:支持apiimplementation依赖方式及Jar任务;

shadowJar插件

plugins { id "com.github.johnrengelman.shadow" version "6.1.0"}

shadowJar {
        archiveBaseName = baseName
        archiveClassifier = archClassfier
        archiveVersion = version
        manifest {
            attributes('Main-Class': className)
        }

        //exclude properties file
        exclude('system.properties')

        //exclude specified jar
        dependencies {
            exclude(dependency('org.mongodb:mongo-java-driver:3.3.0'))
        }

        //include build.gradle
        from("./") {
            include 'build.gradle'
        }

        //rename package name
        relocate 'com.semon.demo' ,'org.semon.demo'

        //merge conf file
        transform(com.github.jengelman.gradle.plugins.shadow.transformers.AppendingTransformer) {
            resource = 'reference.conf'
        }

        // fix pack file more than 65535 files
        zip64 true
    }

shadowJar主要用于实现以下功能:

  1. 将项目打包成一个fatJar,即将项目指定依赖打入最终生成的目标JAR文件中;
  2. 替换目标JAR文件中的包名称;
  3. 将资源文件合并到一个文件中;

IDEA软件配置

IDEA代码模板配置

  • 创建类模板:编辑IDEA--> Perferences --> Editor --> Code Style --> File and Code Templates --> Includes --> File Header,并勾选Enable Live Templates,内容如下:

    /**
    * @Description:
    * @Author: Semon
    * @Version: v1.0
    * @Date: ${DATE} ${TIME}
    */
    
  • 创建方法注释模板:通过IDEA--> Perferences --> Editor --> Code Style --> Live Templates,点击右上角+,添加Template Group后,并在组下添加Live Template,内容如下:

    /**
    * @description:TODO
    * @params: $param$
    * @return: $return$
    */
    1. 点击Edit variables将变量进行映射:
    • $enclosing_method$:映射methodName()
    • $param$:映射methodParameters()
    • $return$:映射methodReturnType()
    1. 点击下方DefineChange关键字,在弹出框中勾选需要生效的语法类型;

    2. 通过右下角Expand with指定调用生成注释快捷键,默认为tab键;使用时,在已生成方法内部输入快捷键即可;

  • 取消IDE开发窗口白线:IDEA --> Perferences --> Editor --> General --> Appearance --> Show hard wrap and visual guides,取消勾选项并应用即可;

  • 取消IDEA黄色警告:

    • IDEA --> Editor --> Code Style --> Inspections --> Declaration redundancy --> Unused declaration取消勾选
    • IDEA --> Editor --> Code Style --> Inspections --> Javadoc --> Dangling Javadoc comment取消勾选
    • IDEA --> Editor --> Code Style --> Inspections --> Javadoc --> Declaration has Javadoc problems取消勾选
  • 取消IDEA绿色波浪线:

    • IDEA --> Editor --> Code Style --> Inspections --> Prooffreading --> Typo取消勾选

文章作者: Semon
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Semon !
评论
  目录