Apache Maven 插件

訪問原文:https://www.ibm.com/developerworks/cn/java/j-5things16/index.html

掌握現代 Maven 插件的技巧





您是否知道 Maven?

Maven 是一個面向 Java™開發人員的領先的依賴管理和構建工具,而且名副其實!它通過闡述項目的構造來標準化軟件構建流程,將它部署爲應用程序,然後與其他項目共享它。

Maven 採用了一組可靠的插件來提供它的所有功能。在 Maven 中,插件擁有目標,在幕後,該目標就是 Java 方法。目標執行構建任務,比如編譯項目,打包它,並將它部署到本地或遠程服務器。這些活動可完美地映射到構建生命週期的各個階段。

Maven 提供了自己的構建插件,這些插件已打包且可立即使用,而且預先配置了默認值。通過「約定高於配置」原則,可以確保能夠針對給定任務的複雜性來擴展配置。大部分構建任務都只需極少的配置。

您還可以自定義 Maven 插件的行爲。使用 Maven 的 <configuration> 元素,很容易重寫插件默認值並定義新值。毫無疑問,大部分重寫的默認值是 compiler 插件的 <source> 和<target> 值。

需要證據?您有多少次將清單 1 中的 XML 添加到 POM 中,以設置正確的 JVM 版本?

清單 1. compiler 插件中的 Java 版本配置
1
2
3
4
5
6
7
8
9
< plugin >
    < groupId >org.apache.maven.plugins</ groupId >
    < artifactId >maven-compiler-plugin</ artifactId >
    < version >3.6.1</ version >
    < configuration >
        < source >1.8</ source >
        < target >1.8</ target >
    </ configuration >
</ plugin >

執行 Maven 生命週期

每個插件目標都映射到一個 Maven 生命週期階段。發出 mvn compile 命令會告訴 mvn 實用程序調用綁定到 compile 生命週期階段的所有目標。compiler 插件的 compile 目標被綁定到這個生命週期階段。

階段與目標之間是一對多的關係。多個插件目標可以綁定到同一個階段,以形成相關任務集合。階段也是分層的,這意味着執行一個階段會導致執行它前面的所有階段

在本例中,發出 mvn compile 命令會啓動 validate 階段(Maven 的默認構建生命週期的第一個階段),並調用綁定到該階段的所有目標。

Maven 和 Google Code 網站維護着一個 Maven 插件列表。這些插件提供了各種各樣有用且省時的功能,您可以將它們整合到構建流程中。我將介紹我發現的一些最有用的插件,並展示如何最充分地利用它們。

1.對 JAR 或 WAR 執行數字簽名

單擊下面的按鈕,下載本示例的代碼。它包含一個簡單的應用程序和一個包含已配置好的 Jarsigner 插件的 POM 文件。

獲取代碼

對 JAR 或 WAR 執行數字簽名是一項重要任務,尤其是在您想分發您的應用程序的時候。幸運的是,Java 平臺提供了一個名爲 jarsigner 的存檔簽名實用程序。它是一個命令行工具,可通過向它傳遞存檔文件的位置和各種參數(比如包含您的加密密鑰的密鑰庫)對存檔文件執行簽名。

可以在 JDK 安裝的 <%JAVA_HOME%>/bin 目錄中找到 jarsigner。清單 2 展示瞭如何使用此實用程序對 JAR 執行簽名。

清單 2. 使用 jarsigner 實用程序對存檔文件執行簽名
1
2
3
4
5
6
jarsigner
     -keystore /path/to/keystore.jks
     -storepass < password >
     -keypass < key password>
     YourArchive.jar
     alias

jarsigner 是一個易於使用的命令行工具,而且開箱即用。 如果能自動化簽名流程,在構建週期的 package 階段對存檔文件執行簽名豈不是更好? 得益於包含 jarsigner 實用程序的 Maven Jarsigner 插件,您可以實現此目標。您只需要將該插件的 sign 目標綁定到您的構建週期的 package 階段。

首先需要一個密鑰庫。如果沒有,可以使用 Java 平臺的 keytool 實用程序創建它,該實用程序可在 JDK 安裝的<%JAVA_HOME%>/bin 目錄中找到。

創建一個密鑰庫

要創建一個密鑰庫,請導航到您想要放置它的位置並執行清單 3 中的命令。一定要將 KeyAlias 替換爲合適的值,比如您的域名。官方 Oracle 文檔詳細介紹了該工具接受的更多配置選項。

清單 3. 爲 jarsigner 實用程序創建一個密鑰庫
1
keytool -genkey -alias < KeyAlias > -keyalg RSA -keystore keystore.jks -keysize 2048

創建密鑰庫的過程要求您回答一系列有關您自己和您的組織的問題,並提供一個安全密碼。配置 Maven Jarsigner 插件時(接下來就會這麼做)將需要此密碼。

將 Jarsigner 添加到您的構建流程中

現在將 Maven Jarsigner 插件添加到您的構建生命週期中,然後配置它來對 package 階段中生成的 JAR 執行數字簽名。關聯到此階段是合理的,因爲已構造 JAR 並將它存儲在您項目的默認輸出目錄中,該目錄通常是 target 目錄。在 POM 文件的 <plugins> 部分,添加清單 4 中所示的代碼。

清單 4. 添加 Jarsigner 插件
1
2
3
4
5
< plugin >
    < groupId >org.apache.maven.plugins</ groupId >
    < artifactId >maven-jarsigner-plugin</ artifactId >
    < version >1.4</ version >
</ plugin >

您想要在構建 JAR 後對它執行簽名,所以需要將簽名過程(包裝在 sign 目標中)連接到 package 生命週期階段。爲此,請將清單 5 中的代碼添加到該插件中。

清單 5. 將 sign 目標連接到 package 階段
1
2
3
4
5
6
7
8
9
< executions >
     < execution >
         < id >sign</ id >
         < phase >package</ phase >
         < goals >
             < goal >sign</ goal >
         </ goals >
     </ execution >
</ executions >

sign 目標需要一些配置細節才能對 JAR 執行數字簽名。所以應該在 <configuration> 元素之間添加密鑰庫位置、您想要使用的憑證的別名、密鑰庫密碼和憑證的密碼,如清單 6 所示。

清單 6. 指定安全憑證
1
2
3
4
5
6
< configuration >
    < keystore >/location/of/keystore.jks</ keystore >
    < alias >KeyAlias</ alias >
    < storepass >password</ storepass >
    < keypass >password</ keypass >
</ configuration >

這是實現 JAR 簽名特性所需的最低配置。請注意,該插件提供了大量額外的配置選項供選擇。

最後一步是構建 JAR 並驗證已對它正確執行簽名。從命令行執行 package 目標,如下所示:mvn clean package。在控制檯輸出中,會看到 JAR 正在構建,然後被簽名。圖 1 展示了您可能看到的結果

圖 1. 輸出顯示已對存檔執行簽名
輸出顯示已對存檔執行簽名

將 JAR 構建到 target 輸出目錄中,這是 Jarsigner 插件期望找到它的位置。該插件將使用您提供的憑證對 JAR 執行簽名,然後向 META-INF 目錄添加兩個額外的文件:一個具有 .SF 擴展名的簽名文件,以及一個具有 .RSA 擴展名的簽名塊文件。

現在已有一個經過數字簽名的 JAR 可供分類。

驗證數字簽名

在分類 JAR 之前,讓我們驗證已對它進行正確簽名。可以使用 Maven Jarsigner 的 verify 目標,或者使用 jarsigner 工具通過命令行來實現此操作。在清單 7 中,我使用了命令行工具並向它傳遞我想要驗證的存檔文件。

清單 7. 使用 jarsigner 實用程序驗證已簽名的 JAR
1
jarsigner -verify target/YourJavaArchive.jar

如果成功,則會收到以下消息:jar verified

對 WAR 文件執行簽名

對 JAR 執行簽名不是 Jarsigner 的唯一功能。該插件可對任何 Java 存檔文件執行簽名,包括 WAR 文件。要查看此操作是如何實現的,可以將 POM 的打包類型從 JAR 更改爲 WAR,添加 Maven WAR 插件(如清單 8 所示)並執行命令:mvn clean package

清單 8. 添加 Maven WAR 插件
1
2
3
4
5
< plugin >
    < groupId >org.apache.maven.plugins</ groupId >
    < artifactId >maven-war-plugin</ artifactId >
    < version >3.1.0</ version >
</ plugin >

檢查 target 目錄,您會找到已簽名的 WAR 文件。

對多個存檔文件執行簽名

如果有多個存檔文件要簽名,Jarsigner 也能應對這種情況。清單 9 中的代碼將 JAR 的簽名位置指定爲 target/all,並且將對此目錄中的所有 JAR 執行簽名。

清單 9. 指定一個存檔目錄
1
< archiveDirectory >target/all</ archiveDirectory >

如果需要更精確地控制要簽名的存檔文件,可以使用通配符來顯式包含和排除文件,如清單 10 所示。

清單 10. 包含和排除選定的存檔文件
1
2
3
4
5
6
< includes >
    < include >*1.0.jar</ include >
</ includes >
< excludes >
    < exclude >*SNAPSHOT.jar</ exclude >
</ excludes >

2.使用 Maven Cargo 部署一個受保護的 Web 應用程序

單擊下面的按鈕,下載本示例的代碼。它包含一個簡單的 Web 應用程序和一個包含已配置好的 Cargo 插件的 POM 文件。

獲取代碼

來自 Codehaus 的 Cargo 插件 是 Cargo API 的一個包裝器。該 API 旨在配置、啓動、停止應用程序並將它部署到各種受支持的容器中,並解析、創建和合並 Java EE 模塊。

一個特別重要的特性是,Cargo 能夠採用容器不可知的方式來指定服務器屬性。這些屬性包括端口、遠程安全憑證、JVM 參數,以及(我們最感興趣的)您想部署的應用程序的用戶登錄細節。該插件支持 14 種最流行的服務器的最新版本。

Cargo 插件最好關聯到 Maven 生命週期的 package 階段中。也可以直接引用 run 目標來獨立執行它:mvn cargo:run。獨立執行會假設該項目已打包且準備好部署。

我們首先將 Cargo 的 run 目標關聯到 package 階段中,如清單 11 所示。

清單 11. 將 Cargo 的 run 目標關聯到 package 階段
1
2
3
4
5
6
7
8
9
10
11
12
13
< plugin >
    < groupId >org.codehaus.cargo</ groupId >
    < artifactId >cargo-maven2-plugin</ artifactId >
    < version >1.6.4</ version >
    < executions >
        < execution >
            < phase >package</ phase >
            < goals >
                < goal >run</ goal >
            </ goals >
        </ execution >
    </ executions >
</ plugin >

完成 Maven 集成後,現在需要對您希望 Cargo 部署應用程序的目標容器進行配置。Cargo 支持各種各樣的容器場景,包括部署到已在運行的本地或遠程服務器(這包括在需要時啓動該服務器)。或者,可以配置 Cargo 來下載、安裝、部署並啓動它支持的 14 種服務器中的任意一種。

對於本示例,我將使用 IBM® WebSphere® Liberty,我已下載它並解壓到一個名爲 servers 的目錄中。

容器配置至少需要容器 ID 和所安裝服務器的主目錄位置。清單 12 給出了位於我的 servers/wlp 目錄中的 Liberty 服務器的配置。

清單 12. 容器配置
1
2
3
4
5
6
< configuration >
    < container >
        < containerId >liberty</ containerId >
        < home >\path\to\servers\wlp</ home >
    </ container >
</ configuration >

下載容器 ZIP 文件

另一個選項是指定 IBM 網站上的 Liberty ZIP 文件的 URL,在這種情況下,Cargo 插件會下載並安裝該服務器。清單 13 顯示了執行此操作的代碼。

清單 13. 從網絡安裝容器
1
2
3
4
5
6
7
8
9
10
11
12
< container >
    < containerId >liberty</ containerId >
    < zipUrlInstaller >
        < url >
               https://public.dhe.ibm.com/ibmdl/export/pub/
               software/websphere/wasdev/downloads/wlp/17.0.0.2/
               wlp-webProfile7-17.0.0.2.zip
        </ url >
        < downloadDir >/path/to/downloadDir</ downloadDir >
        < extractDir >/path/to/extractDir</ extractDir >
    </ zipUrlInstaller >
</ container >

第一次執行 run 目標時,會下載和解壓 ZIP 文件。在後續執行時,Maven 會檢測到該文件已下載和安裝,並跳過該任務。

您現在擁有最少的配置,可以將該應用程序部署到您的服務器中來測試該配置。通過調用 package 階段 (mvn package) 來啓動該流程。將應用程序編譯、打包並部署到服務器中,而且可通過以下 URL 訪問它:http://localhost:8080/{artifactid}/index.html

自定義上下文根目錄

默認情況下,使用 artifactid 來命名 Web 應用程序的上下文根目錄。在某些情況下,您需要指定一個自定義上下文根目錄。在清單 14 中,我將上下文根目錄定義爲 home

清單 14. 自定義上下文根目錄
1
2
3
4
5
6
7
< deployables >
    < deployable >
        < properties >
            < context >home</ context >
        </ properties >
    </ deployable >
</ deployables >

部署應用程序後,可通過以下地址訪問該 Web 應用程序: localhost:8080/home/index.html

指定用戶登錄信息

您現在已有一個非常可靠的部署流程,它會下載並安裝一個服務器,將您的應用程序部署到一個自定義上下文根目錄中。對於 Cargo 插件的功能而言,這纔剛剛開始。

在我們開始定義配置屬性時,Cargo 才真正發揮出它的實力。正如我之前提到的,這些配置屬性是容器的屬性,比如端口、協議,最重要的是用戶登錄細節。

讓我們向示例應用程序添加一個用戶,並強制登錄到該站點。爲了保持簡單,我們將使用基本身份驗證方法,只需要應用程序的 web.xml 文件中的極少配置。清單 15 顯示了 user-role 的規範和對 WelcomeServlet Web 資源的限制。

清單 15. 聲明用戶角色
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
< web-app version = "3.1" ...>
 
    < security-constraint >
        < web-resource-collection >
            < web-resource-name >Welcome Servlet</            <web-resource-name>Welcome Servlet</web-resource-name>
            < url-pattern >/WelcomeServlet/*</ url-pattern >
url-pattern >/WelcomeServlet/*</ url-pattern >
            < http-method >GET</ http-method >
        </ >
相關文章
相關標籤/搜索