第七章. Java 快速入门

Chapter 7. Java Quickstart

7.1. Java 插件

7.1. The Java plugin

如你所见,Gradle是一个通用的构建工具。你在构建脚本中实现的几乎任何内容它都能够构建。它开箱即用,但是需要你在构建脚本中先写好代码。
As we have seen, Gradle is a general-purpose build tool. It can build pretty much anything you care to implement in your build script. Out-of-the-box, however, it doesn't build anything unless you add code to your build script to do so.

大部分的Java项目的基本流程都是类似的:编译Java源文件,运行单元测试,创建一个Jar包。 如果可以不用为每个项目都去编写这些流程那就好了。在实际上,我们确实不用。Gradle通过 插件来解决这一问题。插件就是Gradle的扩展,可以让你以某种方式来配置你的项目,通常通过添加一些预先配置的任务来共同做一些有用的事情。Gradle内置了许多插件,并且你也可以轻松地编写你自己的插件和分享自己的插件。Java plugin是其中之一,这一插件向项目添加一些编译和测试Java源代码,并打包成JAR包的任务。
Most Java projects are pretty similar as far as the basics go: you need to compile your Java source files, run some unit tests, and create a JAR file containing your classes. It would be nice if you didn't have to code all this up for every project. Luckily, you don't have to. Gradle solves this problem through the use of plugins. A plugin is an extension to Gradle which configures your project in some way, typically by adding some pre-configured tasks which together do something useful. Gradle ships with a number of plugins, and you can easily write your own and share them with others. One such plugin is the Java plugin. This plugin adds some tasks to your project which will compile and unit test your Java source code, and bundle it into a JAR file.

这个Java插件是基于约定的。这也意味着它为项目的很多个方面都定义了一些默认值,比如Java源文件的位置。如果你遵循这些约定,那么你就不用在构建脚本中再去做太多的事情。如果你不想或无法遵循约定,Gradle也允许你进行自定义。实际上,由于对Java项目的支持是以插件的形式来实现的,你甚至可以完全不用这个构建来构建Java项目。
The Java plugin is convention based. This means that the plugin defines default values for many aspects of the project, such as where the Java source files are located. If you follow the convention in your project, you generally don't need to do much in your build script to get a useful build. Gradle allows you to customize your project if you don't want to or cannot follow the convention in some way. In fact, because support for Java projects is implemented as a plugin, you don't have to use the plugin at all to build a Java project, if you don't want to.

在后续章节中,我们有深入介绍与Java插件,依赖管理以及多项目构建的相关的许多例子。在本章里,我们还是先了解一下使用Java插件来构建Java项目的基本用法。
We have in-depth coverage with many examples about the Java plugin, dependency management and multi-project builds in later chapters. In this chapter we want to give you an initial idea of how to use the Java plugin to build a Java project.

7.2. 一个基本的 Java 项目

7.2. A basic Java project

让我们来看一个简单的例子。要使用Java插件,只需在构建脚本中添加如下代码:
Let's look at a simple example. To use the Java plugin, add the following to your build file:

示例 7.1. 使用 Java 插件 - Example 7.1. Using the Java plugin

build.gradle

apply plugin: 'java'

注:本示例的代码可以在Gradle的二进制或源代码发行包中的 samples/java/quickstart里找到。
Note: The code for this example can be found at samples/java/quickstart which is in both the binary and source distributions of Gradle.


定义一个Java项目只需要这些就够了。它将会向你的项目应用Java插件,从而添加一些任务。
This is all you need to define a Java project. This will apply the Java plugin to your project, which adds a number of tasks to your project.

有哪些任务可用?

你可以使用 gradle tasks 来列出一个项目的任务,这样就会看到Java插件向项目添加了哪些项目。
You can use gradle tasks to list the tasks of a project. This will let you see the tasks that the Java plugin has added to your project.

What tasks are available?

Gradle会在 src/main/java and your test source code under和 src/test/java能分别找你的生产 源码和测试源码。并且,在 src/main/resources的所有文件都会作为资源被打包进JAR包,任何在 src/test/resources下的资源文件都会被包含到类路径中用于执行测试。所有输出的文件都会在 build 目录里创建,而JAR包会被输出在build/libs 目录里。
Gradle expects to find your production source code under src/main/java and your test source code under src/test/java. In addition, any files under src/main/resources will be included in the JAR file as resources, and any files under src/test/resources will be included in the classpath used to run the tests. All output files are created under the build directory, with the JAR file ending up in the build/libs directory.

7.2.1. 构建项目

7.2.1. Building the project

Java插件向你的项目中添加了不少的任务。但是,在构建项目时只有其中的一部分任务才使用到。最常用的是这个 build 任务,它会对项目做一次完整的构建。当运行 gradle build时,Gradle会编译并执行测试,然后将你的主要类文件和资源文件打成JAR包。
The Java plugin adds quite a few tasks to your project. However, there are only a handful of tasks that you will need to use to build the project. The most commonly used task is the build task, which does a full build of the project. When you run gradle build, Gradle will compile and test your code, and create a JAR file containing your main classes and resources:

示例7.2. 构建Java项目 - Example 7.2. Building a Java project

gradle build的输出结果
Output of gradle build

> gradle build
:compileJava
:processResources
:classes
:jar
:assemble
:compileTestJava
:processTestResources
:testClasses
:test
:check
:build

BUILD SUCCESSFUL

Total time: 1 secs

其他一些有用的任务是:
Some other useful tasks are:

clean

删除build目录,移除所有构建的文件。
Deletes the build directory, removing all built files.

assemble

编译代码并打成jar包,但不会运行单元测试。其他的插件会向这个任务添加更多的工件。例如,如果你使用 War 插件,这个任务也会对你的项目构建出 WAR 文件。
Compiles and jars your code, but does not run the unit tests. Other plugins add more artifacts to this task. For example, if you use the War plugin, this task will also build the WAR file for your project.

check

编译和测试代码。其他的插件会向这一任务添加更多的检查。例如,如果你使用 checkstyle 插件,这一任务就会针对你的源代码运行 Checkstyle 。
Compiles and tests your code. Other plugins add more checks to this task. For example, if you use the checkstyle plugin, this task will also run Checkstyle against your source code.

7.2.2. 外部依赖

7.2.2. External dependencies

通常一个Java项目都会依赖一些外部JAR文件。如果想在项目里引用这些JAR文件,你需要告诉Gradle如何找到这们。在Gradle中,像JAR文件这样的工件都存在于 仓库。仓库可以用于获取项目中的依赖,或是发布项目的工件。在下面的例子中,我们将使用公共的Maven仓库:
Usually, a Java project will have some dependencies on external JAR files. To reference these JAR files in the project, you need to tell Gradle where to find them. In Gradle, artifacts such as JAR files, are located in a repository. A repository can be used for fetching the dependencies of a project, or for publishing the artifacts of a project, or both. For this example, we will use the public Maven repository:

示例 7.3. 添加 Maven 仓库 - Example 7.3. Adding Maven repository

build.gradle

repositories {
    mavenCentral()
}

让我们来添加一些依赖。在这里,我们将声明我们的生产类对commons collection具有编译时依赖,我们的测试类对junit具有需要编译时依赖:
Let's add some dependencies. Here, we will declare that our production classes have a compile-time dependency on commons collections, and that our test classes have a compile-time dependency on junit:

示例 7.4. 添加 依赖 - Example 7.4. Adding dependencies

build.gradle

dependencies {
    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

更多的信息请参阅《第八章,依赖管理基础
You can find out more in Chapter 8, Dependency Management Basics.

7.2.3. 自定义项目

7.2.3. customizing the project

Java插件向你的项目添加了许多属性。这些属性都具有默认值,足以让项目快速开始。如果不符合要求,修改这些值也很简单。让我们在例子中来看。这里,我们会指定我们的Java项目的版本号,以及我们的源码所使用Java版本。我们也会向JAR包的清单文件中添加一些属性。
The Java plugin adds a number of properties to your project. These properties have default values which are usually sufficient to get started. It's easy to change these values if they don't suit. Let's look at this for our sample. Here we will specify the version number for our Java project, along with the Java version our source is written in. We also add some attributes to the JAR manifest.

示例 7.5. 自定义的MANIFEST.MF - Example 7.5. Customization of MANIFEST.MF

build.gradle

sourceCompatibility = 1.5
version = '1.0'
jar {
    manifest {
        attributes 'Implementation-Title': 'Gradle Quickstart', 'Implementation-Version': version
    }
}

有哪些属性可用?

你可以使用 gradle properties来列出一个项目的属性。这个命令会让你看到Java插件所添加的属性以及它们的默认值。
You can use gradle properties to list the properties of a project. This will allow you to see the properties added by the Java plugin, and their default values.

What properties are available?

Java插件所添加的任务都是一些普通任务,与在构建文件里声明的完全一样。这也就是说,你可以利用前面的章节所说的任何机制来自定义这些任务。比如你可以设置一个任务的属性,给它添加一些行为,修改一个任务的依赖,或者是完全地替换掉一个任务。在下面的例子中,我们会配置一个Test类型的 test 任务,使得当执行测试的时候添加一个系统属性:
The tasks which the Java plugin adds are regular tasks, exactly the same as if they were declared in the build file. This means you can use any of the mechanisms shown in earlier chapters to customize these tasks. For example, you can set the properties of a task, add behaviour to a task, change the dependencies of a task, or replace a task entirely. In our sample, we will configure the test task, which is of type Test, to add a system property when the tests are executed:

示例 7.6. 添加一个系统属性 - Example 7.6. Adding a test system property

build.gradle

test {
    systemProperties 'property': 'value'
}

7.2.4. 发布JAR文件

7.2.4. Publishing the JAR file

通常,JAR文件都需要发布到某个地方。为此,你需要告诉Gradle要把JAR文件发布到哪里。在Gradle里,诸如JAR文件这样的工件会被发布到仓库中。在我们的示例中,将发布到一个本地仓库里。当然,你也可以发布到一个远程的位置,或者是多个位置。
Usually the JAR file needs to be published somewhere. To do this, you need to tell Gradle where to publish the JAR file. In Gradle, artifacts such as JAR files are published to repositories. In our sample, we will publish to a local directory. You can also publish to a remote location, or multiple locations.

示例7.7. 发布JAR文件 - Example 7.7. Publishing the JAR file

build.gradle

uploadArchives {
    repositories {
       flatDir {
           dirs 'repos'
       }
    }
}

执行 gradle uploadArchives以发布JAR文件。
To publish the JAR file, run gradle uploadArchives.

7.2.5. 创建一个Eclipse项目

7.2.5. Creating an Eclipse project

要想导入项目到Eclipse中,你需要在你的构建文件中添加另一个插件:
To import your project into Eclipse, you need to add another plugin to your build file:

示例 7.8. Eclipse插件 - Example 7.8. Eclipse plugin

build.gradle

apply plugin: 'eclipse'

现在执行gradle eclipse 命令将生成Eclipse的项目文件。有关Eclipse插件的更多信息请参阅《第三十八章,Eclipse插件》。
Now execute gradle eclipse command to generate Eclipse project files. More on Eclipse task can be found in Chapter 38, The Eclipse Plugin.

7.2.6. 总结

7.2.6. Summary

以下是我们的例子中的完全的构建文件:
Here's the complete build file for our sample:

示例7.9. Java示例——完整的构建文件 - Example 7.9. Java example - complete build file

build.gradle

apply plugin: 'java'
apply plugin: 'eclipse'

sourceCompatibility = 1.5
version = '1.0'
jar {
    manifest {
        attributes 'Implementation-Title': 'Gradle Quickstart', 'Implementation-Version': version
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
}

test {
    systemProperties 'property': 'value'
}

uploadArchives {
    repositories {
       flatDir {
           dirs 'repos'
       }
    }
}

7.3. 多项目的Java构建

7.3. Multi-project Java build

现在让我们来看一个典型的多项目构建。以下是这个项目的布局:
Now let's look at a typical multi-project build. Below is the layout for the project:

示例7.10. 多项目构建——层次布局 - Example 7.10. Multi-project build - hierarchical layout

构建布局
Build layout

multiproject/
  api/
  services/webservice/
  shared/

注:本示例的代码可以在Gradle的二进制或源代码发行包中的 samples/java/multiproject里找到。
Note: The code for this example can be found at samples/java/multiproject which is in both the binary and source distributions of Gradle.


在这里我们有三个项目。项目api会生成一个JAR文件给一个客户端,为您的XML webservice提供一个Java客户端,项目 webservice 是一个返回XML的webapp。项目shared 包含了在 apiwebservice中都会用到的代码。
Here we have three projects. Project api produces a JAR file which is shipped to the client to provide them a Java client for your XML webservice. Project webservice is a webapp which returns XML. Project shared contains code used both by api and webservice.

7.3.1. 定义一个多项目构建

7.3.1. Defining a multi-project build

定义一个多项目构建,需要在源码树的根目录下创建一个设置文件。这个设置文件的名字必须是settings.gradle,它会指定要包含哪些项目。在这个例子中,我们会使用一个简单的层次布局,以下是对应的设置文件:
To define a multi-project build, you need to create a settings file. The settings file lives in the root directory of the source tree, and specifies which projects to include in the build. It must be called settings.gradle. For this example, we are using a simple hierarchical layout. Here is the corresponding settings file:

示例7.11. 多项目构建——settings.gradle文件 - Example 7.11. Multi-project build - settings.gradle file

settings.gradle

include "shared", "api", "services:webservice", "services:shared"

更多的信息可参阅《第五十六章,多项目构建》。
You can find out more about the settings file in Chapter 56, Multi-project Builds.

7.3.2. 公共配置

7.3.2. Common configuration

对于大多数的多项目构建,会有一些共同的配置。在我们的例子中,将会在根项目中使用一种叫做配置注入的技术来定义这些公共配置。在这里,这个根项目就像一个容器,subprojects 的方法会遍历这个容器的一些元素——这个实例中的所有子项目,并且注入指定的配置。这样我们就可以轻松地定义所有存档的清单内容,以及一些公共的依赖:
For most multi-project builds, there is some configuration which is common to all projects. In our sample, we will define this common configuration in the root project, using a technique called configuration injection. Here, the root project is like a container and the subprojects method iterates over the elements of this container - the projects in this instance - and injects the specified configuration. This way we can easily define the manifest content for all archives, and some common dependencies:

示例7.12. 多项目构建——公共配置 - Example 7.12. Multi-project build - common configuration

build.gradle

subprojects {
    apply plugin: 'java'
    apply plugin: 'eclipse-wtp'

    repositories {
       mavenCentral()
}
    }

    dependencies {
        testCompile 'junit:junit:4.11'
}
    }

    version = '1.0'

    jar {
        manifest.attributes provider: 'gradle'
    }
}

注意,我们的例子对每一个子项目都应用了Java插件。这意味着,在前一节我们所看到的任务和配置,在每一个子项目中都是可用的。因此,你可以通过在根项目目录中运行gradle build,对所有的项目编译,测试并打成JAR包。
Notice that our sample applies the Java plugin to each subproject. This means the tasks and configuration properties we have seen in the previous section are available in each subproject. So, you can compile, test, and JAR all the projects by running gradle build from the root project directory.

7.3.3. 项目中的依赖

7.3.3. Dependencies between projects

你可以向同一个构建的项目之间添加依赖关系,这样,某个项目中的 JAR 文件就能用于编译另一个项目了。在 api项目的构建文件里,我们让它依赖 shared 项目所生成的JAR文件。由于这个依赖关系,Gradle会确保 shared项目总是在 api项目之前构建。
You can add dependencies between projects in the same build, so that, for example, the JAR file of one project is used to compile another project. In the api build file we will add a dependency on the JAR produced by the shared project. Due to this dependency, Gradle will ensure that project shared always gets built before project api.

示例7.13. 多项目构建——项目间的依赖 - Example 7.13. Multi-project build - dependencies between projects

api/build.gradle

dependencies {
    compile project(':shared')
}

参阅 第56.7.1节,“禁用项目依赖” 来了解如何停用该功能。

7.3.4. 创建分发

7.3.4. Creating a distribution

在下面的例子中,我们创建了一个分发,来发送给客户端:
We also add a distribution, that gets shipped to the client:

示例7.14. 多项目构建——分发文件 - Example 7.14. Multi-project build - distribution file

api/build.gradle

task dist(type: Zip) {
    dependsOn spiJar
    from 'src/dist'
    into('libs') {
        from spiJar.archivePath
        from configurations.runtime
    }
}

artifacts {
   archives dist
}

7.4. 下一步目标?

7.4. Where to next?

在本章中,你已经学习了如何构建一个基于Java的项目。本章节只是简单介绍,Gradle对Java项目可以做的事情还有很多。你可以在《第二十三章,Java插件》中对Java插件进行进一步了解,更多的Java项目示例请在Gradle分发包中的samples/java目录中查看。
In this chapter, you have seen how to do some of the things you commonly need to build a Java based project. This chapter is not exhaustive, and there are many other things you can do with Java projects in Gradle. You can find out more about the Java plugin in Chapter 23, The Java Plugin, and you can find more sample Java projects in the samples/java directory in the Gradle distribution.

另外,下一章是《第八章,依赖管理基础》。
Otherwise, continue on to Chapter 8, Dependency Management Basics.