乐趣区

关于java:在gradle中构建java项目

简介

之前的文章咱们讲到了 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/

最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!

欢送关注我的公众号:「程序那些事」, 懂技术,更懂你!

退出移动版