天天看點

在gradle中建構java項目簡介建構java項目的兩大插件管理依賴編譯代碼管理resource打包和釋出生成javadoc

簡介

之前的文章我們講到了gradle的基本使用,使用gradle的最終目的就是為了建構java項目。今天本文将會詳細的講解如何在gradle中建構java項目。

建構java項目的兩大插件

安裝java項目的目的不同,建構java項目有兩大插件,一個是application,表示建構的是java應用程式;一個是java-library,表示建構的是java庫,供别的項目使用。

不管是建構應用程式還是java庫,我們都可以很友善的使用gradle init來創新一個新的gradle項目:

$ gradle init

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 2

Select implementation language:
  1: C++
  2: Groovy
  3: Java
  4: Kotlin
  5: Scala
  6: Swift
Enter selection (default: Java) [1..6] 3

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Select test framework:
  1: JUnit 4
  2: TestNG
  3: Spock
  4: JUnit Jupiter
Enter selection (default: JUnit 4) [1..4]

Project name (default: demo):
Source package (default: demo):


BUILD SUCCESSFUL
2 actionable tasks: 2 executed           

application和library的不同之處在于第二步選擇的不同。

兩者在build.gradle中的不同在于plugins的不同,application的plugin是:

plugins {
    id 'application' 
}           

而library的plugin是:

plugins {
    id 'java-library' 
}           

還有一個不同之處是依賴的不同,先看一個application的依賴:

dependencies {
    testImplementation 'junit:junit:4.13' 

    implementation 'com.google.guava:guava:29.0-jre' 
}           

再看一個library的依賴:

dependencies {
    testImplementation 'junit:junit:4.13' 

    api 'org.apache.commons:commons-math3:3.6.1' 

    implementation 'com.google.guava:guava:29.0-jre' 
}           

因為library是需要給第三方應用程式使用的,是以這裡多了一個api的使用,api表示是第三方應用程式也需要依賴這個包,而implementation表示的是該包隻是在這個項目内部被依賴。

在建構libary的時候,還可以自定義manifest的資訊:

tasks.named('jar') {
    manifest {
        attributes('Implementation-Title': project.name,
                   'Implementation-Version': project.version)
    }
}           

上面的例子将會在META-INF/MANIFEST.MF生成:

Manifest-Version: 1.0
Implementation-Title: lib
Implementation-Version: 0.1.0           

我們還可以指定編譯的java版本号和lib的版本:

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(11)
    }
}

version = '1.2.1'           

管理依賴

java的依賴一般都是jar包組成的library。和maven一樣,我們在gradle中指定依賴需要指定依賴的名字和版本号,依賴的範圍:是運作時依賴還是編譯時依賴,還有一個重要的就是在哪裡可以找到這個library。

前面兩個屬性我們可以在dependencies中找到,後面一個我們可以在repositories中找到,看一個例子:

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.hibernate:hibernate-core:3.6.7.Final'
}           

還可以使用這種形式的maven:

repositories {
    maven {
        url "http://repo.mycompany.com/maven2"
    }
}           

或者Ivy:

repositories {
    ivy {
        url "http://repo.mycompany.com/repo"
    }
}           

甚至可以使用本地的local dir:

repositories {
    flatDir {
        dirs 'lib'
    }
    flatDir {
        dirs 'lib1', 'lib2'
    }
}           

上面定義了一個mavenCentral的倉庫,我們可以在這個倉庫中去查找hibernate-core這個依賴的jar包。

在dependencies這一塊,我們可以定義依賴包的工作範圍:

  • compileOnly: 表示依賴包隻被用來編譯代碼,并不用在程式的運作。
  • implementation:表示依賴包被用在編譯和運作時。
  • runtimeOnly: 隻在運作時使用。
  • testCompileOnly: 僅在test的編譯時使用。
  • testImplementation:在test的編譯和運作時使用。
  • testRuntimeOnly: 在test的運作時使用。

我們還可以添加動态的依賴:

dependencies {
    implementation 'org.springframework:spring-web:5.+'
}           

使用項目作為依賴:

dependencies {
    implementation project(':shared')
}           

編譯代碼

一般情況下你的源代碼需要放在src/main/java 目錄下,測試代碼需要放在src/test/java下面。然後添加compileOnly 或者 implementation依賴,如果需要測試的話,添加testCompileOnly或者testImplementation依賴。

然後就可以運作compileJava和compileTestJava來編譯代碼了。

當然,如果你有自定義的源檔案目錄,也可以這樣手動指定:

sourceSets {
    main {
         java {
            srcDirs = ['src']
         }
    }

    test {
        java {
            srcDirs = ['test']
        }
    }
}           

上面的代碼中我們給srcDirs重新指派了。如果我們隻是想要在現有的代碼路徑上再添加一個新的路徑,那麼可以使用srcDir:

sourceSets {
    main {
        java {
            srcDir 'thirdParty/src/main/java'
        }
    }
}           

除了源代碼的路徑,我們還可以配置編譯的參數,并指定編譯的JDK版本号:

compileJava {
    options.incremental = true
    options.fork = true
    options.failOnError = false
    options.release = 7
}           
注意,gradle必須要在JDK8以上才能運作,但是我們可以指定gradle去使用Java 6 或者 Java 7去編譯源代碼。

我們還可以指定預覽版本的特性:

tasks.withType(JavaCompile) {
    options.compilerArgs += "--enable-preview"
}
tasks.withType(Test) {
    jvmArgs += "--enable-preview"
}
tasks.withType(JavaExec) {
    jvmArgs += "--enable-preview"
}           

管理resource

java除了源代碼檔案之外,還有一些resource檔案,比如配置檔案,圖檔檔案,語言檔案等等。我們需要将這些配置檔案拷貝到特定的目标目錄中。

預設情況下,gradle會拷貝src/[sourceSet]/resources 中的檔案到目标檔案夾中。

我們看一個複雜的拷貝動作:

task copyDocs(type: Copy) {
    from 'src/main/doc'
    into 'build/target/doc'
}

//for Ant filter
import org.apache.tools.ant.filters.ReplaceTokens

//for including in the copy task
def dataContent = copySpec {
    from 'src/data'
    include '*.data'
}

task initConfig(type: Copy) {
    from('src/main/config') {
        include '**/*.properties'
        include '**/*.xml'
        filter(ReplaceTokens, tokens: [version: '2.3.1'])
    }
    from('src/main/config') {
        exclude '**/*.properties', '**/*.xml'
    }
    from('src/main/languages') {
        rename 'EN_US_(.*)', '$1'
    }
    into 'build/target/config'
    exclude '**/*.bak'

    includeEmptyDirs = false

    with dataContent
}           

打包和釋出

我們可以根據不同的建構類型來打包對應的檔案。比如對應java lib來說,我們可以同時上傳源代碼和java doc檔案:

java {
    withJavadocJar()
    withSourcesJar()
}           

比如說我們還可以打包成一個fat jar包:

plugins {
    id 'java'
}

version = '1.0.0'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'commons-io:commons-io:2.6'
}

task uberJar(type: Jar) {
    archiveClassifier = 'uber'

    from sourceSets.main.output

    dependsOn configurations.runtimeClasspath
    from {
        configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) }
    }
}           

生成javadoc

gradle的java library插件有一個javadoc task,可以為java項目生成文檔。它支援标準的javadoc,也支援其他類型的文檔,比如說Asciidoc,我們看一個生成Asciidoc的例子:

configurations {
    asciidoclet
}

dependencies {
    asciidoclet 'org.asciidoctor:asciidoclet:1.+'
}

task configureJavadoc {
    doLast {
        javadoc {
            options.doclet = 'org.asciidoctor.Asciidoclet'
            options.docletpath = configurations.asciidoclet.files.toList()
        }
    }
}

javadoc {
    dependsOn configureJavadoc
}           
本文已收錄于 http://www.flydean.com/gradle-build-java-projects/

最通俗的解讀,最深刻的幹貨,最簡潔的教程,衆多你不知道的小技巧等你來發現!

歡迎關注我的公衆号:「程式那些事」,懂技術,更懂你!