這篇教程的主要內(nèi)容是講解如何用Gradle編譯和打包一個簡單的Java項(xiàng)目,。
該Java項(xiàng)目只有一個需求:我們的構(gòu)建腳本必須創(chuàng)建一個可執(zhí)行的Jar文件,,換句話說,,我們必須能夠使用命令java -jar jarfile.jar 來運(yùn)行我們的程序。我們來看一下如何滿足這個需求,。
創(chuàng)建一個Java項(xiàng)目
我們可以使用Java插件(譯注:關(guān)于Gradle插件的定義,,請查看第一篇教程)來創(chuàng)建一個Java項(xiàng)目,為了做到這點(diǎn),,我們需要把下面這段語句加入到build.gradle文件中:
就是這樣,,現(xiàn)在我們已經(jīng)創(chuàng)建了一個Java項(xiàng)目。Java插件會在我們的構(gòu)建中添加一些新的約定(如默認(rèn)的項(xiàng)目結(jié)構(gòu)),,新的任務(wù),,和新的屬性。
讓我們來快速地看一下默認(rèn)的項(xiàng)目結(jié)構(gòu),。
Java項(xiàng)目結(jié)構(gòu)
默認(rèn)的項(xiàng)目結(jié)構(gòu)如下:
- src/main/java目錄包含了項(xiàng)目的源代碼,。
- src/main/resources目錄包含了項(xiàng)目的資源(如屬性文件)。
- src/test/java目錄包含了測試類,。
- src/test/resources目錄包含了測試資源,。所有我們構(gòu)建生成的文件都會在build目錄下被創(chuàng)建,這個目錄涵蓋了以下的子目錄,,這些子目錄我們會在這篇教程中提到,,另外還有一些子目錄我們會放在以后講解。
- classes目錄包含編譯過的.class文件,。
- libs目錄包含構(gòu)建生成的jar或war文件,。
為構(gòu)建加入一個主類(main class)
讓我們創(chuàng)建一個簡單的主類,在這個類中會打印一個“Hello world”然后System.out出來,。這個HelloWorld類的源代碼如下:
1 2 3 4 5 6 7 8 | package net.petrikainulainen.gradle;
public class HelloWorld {
public static void main(String[] args) {
System.out.println( "Hello World!" );
}
}
|
HelloWorld類存放在src/main/java/net/petrikainulainen/gradle目錄
這很好,,然而,我們還需要編譯和打包我們的項(xiàng)目,,不是嗎,?我們先看一下這個Java工程中的任務(wù)。
Java工程中的任務(wù)
Java插件在我們的構(gòu)建中加入了很多任務(wù),,我們這篇教程涉及到的任務(wù)如下:
- assemble任務(wù)會編譯程序中的源代碼,,并打包生成Jar文件,這個任務(wù)不執(zhí)行單元測試,。
- build任務(wù)會執(zhí)行一個完整的項(xiàng)目構(gòu)建,。
- clean任務(wù)會刪除構(gòu)建目錄。
- compileJava任務(wù)會編譯程序中的源代碼,。
我們還可以執(zhí)行以下命令得到一個可運(yùn)行任務(wù)及其描述的完整列表
這是一個很好的方式,,不需要閱讀構(gòu)建腳本,,就能對你的項(xiàng)目進(jìn)行大致的瀏覽,如果我們在項(xiàng)目根目錄下運(yùn)行這個命令,,我們可以看到以下輸出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | > gradle tasks
:tasks
------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------
Build tasks
-----------
assemble - Assembles the outputs of this project.
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 classes 'main' .
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes.
testClasses - Assembles classes 'test' .
Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]
Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the main source code.
Help tasks
----------
dependencies - Displays all dependencies declared in root project 'first-java-project' .
dependencyInsight - Displays the insight into a specific dependency in root project 'first-java-project' .
help - Displays a help message
projects - Displays the sub-projects of root project 'first-java-project' .
properties - Displays the properties of root project 'first-java-project' .
tasks - Displays the tasks runnable from root project 'first-java-project' .
Verification tasks
------------------
check - Runs all checks.
test - Runs the unit tests.
Rules
-----
Pattern: build<ConfigurationName>: Assembles the artifacts of a configuration.
Pattern: upload<ConfigurationName>: Assembles and uploads the artifacts belonging to a configuration.
Pattern: clean<TaskName>: Cleans the output files of a task.
To see all tasks and more detail, run with --all.
BUILD SUCCESSFUL
Total time : 2.792 secs
|
我們繼續(xù),,下面要講怎樣打包我們的項(xiàng)目。
打包我們的項(xiàng)目
我們可以通過使用兩個不同的任務(wù)來打包項(xiàng)目,。
如果我們在命令提示符中執(zhí)行命令gradle assemble,,我們可以看到以下輸出:
1 2 3 4 5 6 7 8 9 10 | > gradle assemble
:compileJava
:processResources
:classes
:jar
:assemble
BUILD SUCCESSFUL
Total time : 3.163 secs
|
如果我們在命令提示符中執(zhí)行命令gradle build,我們可以看到以下輸出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | > gradle build
:compileJava
:processResources
:classes
:jar
:assemble
:compileTestJava
:processTestResources
:testClasses
: test
:check
:build
BUILD SUCCESSFUL
Total time : 3.01 secs
|
這些命令的輸出表明了它們的區(qū)別:
- assemble任務(wù)僅僅執(zhí)行項(xiàng)目打包所必須的任務(wù)集,。
- build任務(wù)執(zhí)行項(xiàng)目打包所必須的任務(wù)集,,以及執(zhí)行自動化測試。這兩個命令都會在build/libs目錄中創(chuàng)建一個file-java-project.jar文件,。默認(rèn)創(chuàng)建的Jar文件名稱是由這個模版決定的:[projectname].jar,,此外,項(xiàng)目的默認(rèn)名稱和其所處的目錄名稱是一致的,。因此如果你的項(xiàng)目目錄名稱是first-java-project,,那么創(chuàng)建的Jar文件名稱就是first-java-project.jar。
現(xiàn)在,,我們嘗試使用以下命令運(yùn)行我們的程序:
1 | java -jar first-java-project.jar
|
我們可以看到以下輸出:
1 2 | > java -jar first-java.project.jar
No main manifest attribute, in first-java-project.jar
|
問題出在,,我們沒有在manifest文件中配置Jar文件的主類,讓我們繼續(xù)看看怎樣解決這個問題,。
配置Jar文件的主類
Java插件在我們的項(xiàng)目中加入了一個Jar任務(wù),,每一個Jar對象都一個manifest屬性,這個屬性是Manifest的一個實(shí)例,。
我們可以對生成的Jar文件的主類進(jìn)行配置,,使用Manifest接口的attributes()方法。換句話說,,我們可以使用一個包含鍵值對的map結(jié)構(gòu)指定加入到manifest文件的屬性集,。
我們能夠通過設(shè)置Main-Class屬性的值,,指定我們程序的入口點(diǎn),。在我們對build.gradle文件進(jìn)行必要的改動后,代碼如下:
1 2 3 4 5 6 7 | apply plugin: 'java'
jar {
manifest {
attributes 'Main-Class' : 'net.petrikainulainen.gradle.HelloWorld'
}
}
|
(JavaSE教程提供了關(guān)于manifest文件的更多信息,。)
在我們執(zhí)行gradle assemble或gradle build命令生成一個新的jar文件之后,,我們可以執(zhí)行以下命令運(yùn)行jar文件:
1 | java -jar first-java-project.jar
|
當(dāng)我們運(yùn)行程序時,System.out會打印出以下信息:
1 2 | > java -jar first-java-project.jar
Hello World!
|
這就是我們今天所有的內(nèi)容,,我們看一下我們學(xué)到了什么,。
總結(jié)
我們已經(jīng)通過Gradle創(chuàng)建了一個簡單的Java項(xiàng)目,這篇教程教會了我們四點(diǎn):
- 我們了解了可以使用Gradle的Java插件創(chuàng)建一個Java項(xiàng)目,。
- 我們知道了Java項(xiàng)目的默認(rèn)結(jié)構(gòu)和Maven項(xiàng)目的默認(rèn)結(jié)構(gòu)是一樣的,。
- 我們知道了構(gòu)建所生成的所有文件都能在build目錄下找到,。
- 我們知道了我們可以自定義加入到manifest文件中的屬性。
P.S. 這篇教程的示例代碼可以在Github找到,。
|