The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

認識 Apache Maven 優異的 Java 專案範本引擎 - Maven Archetype Plugin

現在很多 Java 的 IDE 工具都有內建 Maven Archetype Plugin 作為建立新專案時的專案範本,你只要安裝 Apache Maven 之後,也可以很輕易的透過 CLI 介面來使用。今天這篇文章我想來介紹這套工具,並且分享一個可以大幅提昇執行速度的小技巧。

Maven Archetype Plugin 簡介

Archetype Plugin 允許使用者從一個既有的專案範本,快速建立一個以 Maven 為基礎的全新專案。而在 Maven 的世界裡,這個專案範本又稱 archetype (原型)。

關於 archetype 這個英文單字由於對台灣人來說比較陌生,比較難用中文好好理解,但從英英字典的翻譯中可以看到他的定義是 "a very typical example of a particular type of person or thing",簡單翻譯一下這句的意思就是:「一種特定人事物類型的經典範例」。因此,你可以把 archetype 思考為:「我有一種特定用途的應用程式類型,我為這種應用程式設計了一個原型,好讓日後要開發這類應用程式的人,可以依據這個原型為基礎,打造一個全新的應用程式」。

Maven Archetype Plugin 主要架構

Archetype Plugin 主要的任務就只有兩個:

  1. 從既有 archetype 建立新專案
  2. 從既有專案建立 archetype

他的整體架構如下:

Maven Archetype Plugin Overview

從既有 archetype 建立新專案

要使用 Archetype Plugin 其實非常簡單,主要有三個步驟:

  1. 準備一個 archetype 的來源

    預設 archetype 有三種不同的來源,這個來源又稱 archetypeCatalog (原型類別),分別是 remote, local, internal 三種。

    當你在執行 mvn archetype:generate 命令的時候,這個 archetypeCatalog (原型類別) 的預設值為 remote,local,因此每次建立專案時,都會先從 remote (遠端) 下載一份 archetype 原型類別回來 (archetype-catalog.xml),再去抓 local (本地) 的原型類別。

    所謂 remote 原型類別,就是官方從 ArchetypeCatalog 維護的一份清單。裡面包含了許多社群提交的專案範本。

    所謂 local 原型類別,就是你在本機曾經使用過的專案範本,或是你直接從本地專案產生的專案範本。

    所謂 internal 原型類別,就是 Maven Archetype Plugin 內建的專案範本。

  2. 選擇一份 archetype 當成專案範本

    由於預設這份來自遠端的 archetype-catalog.xml 原型類別還蠻大的,內容是一份 XML 檔案,整體大小有 12.3MB 之多,當 repo.maven.apache.org 網站的連線速度變慢的時候,下載時間可能會高達 2 分鐘之久,快的時候大概 2 ~ 3 秒左右。

    你可以試試輸入以下命令,他會列出三千多份 archetype 讓你選擇,是不是很多!😅

    mvn archetype:generate -DarchetypeCatalog=remote
    

    我把這 3,000 多份 archetype 放在我的 Gist 讓大家可以方便快速瀏覽!

    由於 archetype 非常多,你也可以用以下命令提供篩選條件 (-Dfilter=[groupId:]artifactId):

    mvn archetype:generate -Dfilter=am.ik.archetype:spring
    

    image

  3. 提供這份 archetype 專案範本所需的參數設定

    由於每份 archetype 專案範本都可以自訂參數傳入,因此每個 archetype 可能會用到的參數都不太一樣。不過,你在執行 mvn archetype:generate 時,預設就會選用互動模式(-Dinteractive=true),因此你在建立專案的時候,他會在 CLI 介面提醒你該設定些什麼,所以沒甚麼好擔心的。

    如果要用非互動模式(-Dinteractive=false)或稱批次模式(-B)來執行的話,可能就要設法取得所有參數才能執行。例如我以建立 Spring Boot 專案為例,你可能需要這樣執行:

    Bash

    mvn archetype:generate -B \
      -DarchetypeGroupId=am.ik.archetype \
      -DarchetypeArtifactId=spring-boot-blank-archetype \
      -DarchetypeVersion=1.0.6 \
      -DgroupId=com.duotify \
      -DartifactId=demo1 \
      -Dversion=1.0-SNAPSHOT
    

    PowerShell

    mvn archetype:generate -B `
      '-DarchetypeGroupId=am.ik.archetype' `
      '-DarchetypeArtifactId=spring-boot-blank-archetype' `
      '-DarchetypeVersion=1.0.6' `
      '-DgroupId=com.duotify' `
      '-DartifactId=demo2' `
      '-Dversion=1.0-SNAPSHOT'
    

    Command Prompt

    mvn archetype:generate -B ^
      -DarchetypeGroupId=am.ik.archetype ^
      -DarchetypeArtifactId=spring-boot-blank-archetype ^
      -DarchetypeVersion=1.0.6 ^
      -DgroupId=com.duotify ^
      -DartifactId=demo3 ^
      -Dversion=1.0-SNAPSHOT
    

    三種不同的 Shell 環境有不同的命令寫法,文章真的很難寫!😅

提升建立新專案的速度

我有發現用 mvn archetype:generate 建立專案時,執行速度異常的慢,就是因為 archetypeCatalog (原型類別) 的預設值為 remote,local,所以無論如何他都一定會先下載 archetype-catalog.xml 回來,浪費了頻寬,也浪費了寶貴的時間。

我們曾經用過的 archetype,其實都會透過 mvn 下載到 local 的 Maven Repository 裡面,如果你認為不會有新版的話,其實可以把指令稍微調整一下,跳過 archetypeCatalogremote 來源即可。以下我用 PowerShell 為例:

  • 選用 -DarchetypeCatalog=local 本地原型類別

    mvn archetype:generate -B `
      '-DarchetypeCatalog=local' `
      '-DarchetypeGroupId=am.ik.archetype' `
      '-DarchetypeArtifactId=spring-boot-blank-archetype' `
      '-DarchetypeVersion=1.0.6' `
      '-DgroupId=com.duotify' `
      '-DartifactId=demo2' `
      '-Dversion=1.0-SNAPSHOT'
    
  • 選用 -DarchetypeCatalog=internal 內建原型類別

    mvn archetype:generate -B `
      '-DarchetypeCatalog=internal' `
      '-DarchetypeGroupId=am.ik.archetype' `
      '-DarchetypeArtifactId=spring-boot-blank-archetype' `
      '-DarchetypeVersion=1.0.6' `
      '-DgroupId=com.duotify' `
      '-DartifactId=demo2' `
      '-Dversion=1.0-SNAPSHOT'
    

其實你在 internallocal 原型類別,都找不到 am.ik.archetype:spring-boot-blank-archetype 這份 archetype 才對,但這個命令可以讓你跳過下載 remote 目錄,找不到之後,就會直接從 local 的 Maven Repository 找到 am.ik.archetype:spring-boot-blank-archetype 這份 Artifact,所以一樣可以安裝成功,而且可以讓執行時間從 2 分鐘驟降到 1 ~ 2 秒左右!👍

參考: Generate project using an alternative catalog

從既有專案建立 archetype

完整的建立過程可以參考 Archetype creation 文件說明,實作的步驟如下:

  1. 建立 ~/.m2/settings.xml 檔案

    由於 Maven 預設並不會幫你產生 ~/.m2/settings.xml 檔案,你必須手動建立這份 XML 檔才能進行下一步:

    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
      <localRepository/>
      <interactiveMode/>
      <offline/>
      <pluginGroups/>
      <servers/>
      <mirrors/>
      <proxies/>
      <profiles/>
      <activeProfiles/>
    </settings>
    

    詳見 Settings ReferenceWhy maven settings.xml file is not there? - Stack Overflow

  2. 找到一個現有的 Maven 專案,執行以下命令

    mvn archetype:create-from-project
    

    這個命令會將現有專案在 target/generated-sources/archetype 資料夾建立一個 archetype 專案,而且它會全自動幫你把現有專案的原始碼進行調整,調整成「專案範本」的樣子,在 target/generated-sources/archetype/pom.xml 檔案中會有這個 archetype 專案的完整資訊。

  3. 微調剛建立的 archetype 專案

    如我在 如何將私有的 JAR 檔加入到由 Apache Maven 管理的 Java 專案中 文章中提到的觀念,這個 pom.xml 檔案中有四個最重要的參數,記得要先調整一下,尤其是 version 的設定:

    <groupId>com.duotify</groupId>
    <artifactId>myapp-archetype</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>maven-archetype</packaging>
    

    如果你希望在未來建立新專案後可以執行一些程式碼,做一些專案的結構調整或是做一些檔案的初始化動作,你可以在 target/generated-sources/archetype/src/main/resources/META-INF/ 目錄下建立一個 archetype-post-generate.groovy 程式,只要用 Apache Groovy 語言撰寫這份腳本即可。

  4. 將新的 archetype 專案安裝到 local Maven Repository 裡面

    cd target/generated-sources/archetype/
    mvn install
    
  5. 測試從 local 原型類別來源建立一個新專案

    先建立一個空資料夾,並從 local 原型類別來源建立一個新專案

    mvn archetype:generate -DarchetypeCatalog=local
    

    你也可以用 -B 批次模式快速建立新專案:

    mvn archetype:generate -B `
      '-DarchetypeCatalog=local' `
      '-DarchetypeGroupId=com.duotify' `
      '-DarchetypeArtifactId=myapp-archetype' `
      '-DarchetypeVersion=0.0.1-SNAPSHOT' `
      '-DgroupId=com.duotify' `
      '-DartifactId=demo2' `
      '-Dversion=1.0'
    

更多 Maven Archetype Plugin 用法

  • 查詢 Archetype Plugin 不同 goal 的用法說明:

    mvn archetype:help -Ddetail=true
    

    詳見 Maven Archetype Plugin - Plugin Documentation

  • 更新位於 localarchetype 的來源

    這個命令在官網並沒有寫的很清楚,但他的意思就是將你當前目錄下的 archetype 專案重新建置,並且更新 ~/.m2/repository/archetype-catalog.xml 檔案。

    mvn archetype:update-local-catalog
    

    你必須在 target/generated-sources/archetype/ 目錄下執行這個命令。

相關連結