這篇教程的主要內容是講解如何用Gradle編譯和打包一個簡單的Java專案。
該Java專案只有一個需求:我們的構建指令碼必須建立一個可執行的Jar檔案,換句話說,我們必須能夠使用命令java -jar jarfile.jar 來執行我們的程式。我們來看一下如何滿足這個需求。
建立一個Java專案
我們可以使用Java外掛(譯註:關於Gradle外掛的定義,請檢視第一篇教程)來建立一個Java專案,為了做到這點,我們需要把下面這段語句加入到build.gradle檔案中:
1 |
apply plugin: 'java' |
就是這樣,現在我們已經建立了一個Java專案。Java外掛會在我們的構建中新增一些新的約定(如預設的專案結構),新的任務,和新的屬性。
讓我們來快速地看一下預設的專案結構。
Java專案結構
預設的專案結構如下:
- src/main/java目錄包含了專案的原始碼。
- src/main/resources目錄包含了專案的資源(如屬性檔案)。
- src/test/java目錄包含了測試類。
- src/test/resources目錄包含了測試資源。所有我們構建生成的檔案都會在build目錄下被建立,這個目錄涵蓋了以下的子目錄,這些子目錄我們會在這篇教程中提到,另外還有一些子目錄我們會放在以後講解。
- classes目錄包含編譯過的.class檔案。
- libs目錄包含構建生成的jar或war檔案。
為構建加入一個主類(main class)
讓我們建立一個簡單的主類,在這個類中會列印一個“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目錄
這很好,然而,我們還需要編譯和打包我們的專案,不是嗎?我們先看一下這個Java工程中的任務。
Java工程中的任務
Java外掛在我們的構建中加入了很多工,我們這篇教程涉及到的任務如下:
- assemble任務會編譯程式中的原始碼,並打包生成Jar檔案,這個任務不執行單元測試。
- build任務會執行一個完整的專案構建。
- clean任務會刪除構建目錄。
- compileJava任務會編譯程式中的原始碼。
我們還可以執行以下命令得到一個可執行任務及其描述的完整列表
1 |
gradle tasks |
這是一個很好的方式,不需要閱讀構建指令碼,就能對你的專案進行大致的瀏覽,如果我們在專案根目錄下執行這個命令,我們可以看到以下輸出:
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 |
我們繼續,下面要講怎樣打包我們的專案。
打包我們的專案
我們可以通過使用兩個不同的任務來打包專案。
如果我們在命令提示符中執行命令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 |
如果我們在命令提示符中執行命令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 |
這些命令的輸出表明瞭它們的區別:
- assemble任務僅僅執行專案打包所必須的任務集。
- build任務執行專案打包所必須的任務集,以及執行自動化測試。這兩個命令都會在build/libs目錄中建立一個file-java-project.jar檔案。預設建立的Jar檔名稱是由這個模版決定的:[projectname].jar,此外,專案的預設名稱和其所處的目錄名稱是一致的。因此如果你的專案目錄名稱是first-java-project,那麼建立的Jar檔名稱就是first-java-project.jar。
現在,我們嘗試使用以下命令執行我們的程式:
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檔案的主類,讓我們繼續看看怎樣解決這個問題。
配置Jar檔案的主類
Java外掛在我們的專案中加入了一個Jar任務,每一個Jar物件都一個manifest屬性,這個屬性是Manifest的一個例項。
我們可以對生成的Jar檔案的主類進行配置,使用Manifest介面的attributes()方法。換句話說,我們可以使用一個包含鍵值對的map結構指定加入到manifest檔案的屬性集。
我們能夠通過設定Main-Class屬性的值,指定我們程式的入口點。在我們對build.gradle檔案進行必要的改動後,程式碼如下:
1 2 3 4 5 6 7 |
apply plugin: 'java' jar { manifest { attributes 'Main-Class': 'net.petrikainulainen.gradle.HelloWorld' } } |
(JavaSE教程提供了關於manifest檔案的更多資訊。)
在我們執行gradle assemble或gradle build命令生成一個新的jar檔案之後,我們可以執行以下命令執行jar檔案:
1 |
java -jar first-java-project.jar |
當我們執行程式時,System.out會列印出以下資訊:
1 2 |
> java -jar first-java-project.jar Hello World! |
這就是我們今天所有的內容,我們看一下我們學到了什麼。
總結
我們已經通過Gradle建立了一個簡單的Java專案,這篇教程教會了我們四點:
- 我們瞭解了可以使用Gradle的Java外掛建立一個Java專案。
- 我們知道了Java專案的預設結構和Maven專案的預設結構是一樣的。
- 我們知道了構建所生成的所有檔案都能在build目錄下找到。
- 我們知道了我們可以自定義加入到manifest檔案中的屬性。
P.S. 這篇教程的示例程式碼可以在Github找到。