開發一個maven腳手架


寫在前面

開發新項目就需要搭建新工程,但是搭建新工程的這個過程是非常繁瑣浪費時間的,並且不可避免的需要踩坑。更可怕的是,如果是在一個團隊中,每新起一個項目都由不同的開發人員去自定義的搭建工程結構,那么對后續的統一管理,監控,運維簡直是災難。基於以上幾點,團隊內部其實是非常有必要搭建一個統一的腳手架來供統一使用

制作一個腳手架

下面我們就來詳細的介紹如何搭建一個maven工程的腳手架

要搭建腳手架,首先我們需要一個模板工程,這個模板工程一般來說會集成一些工具類,底層中間件,通用配置,並且要有良好的分層結構等。需要能夠達到開箱即用的程度。

以下是一個模板工程的目錄結構,也是目前我們團隊內部的標准化結構

.
├── example-client
│   ├── pom.xml
│   └── src
├── example-core
│   ├── pom.xml
│   └── src
├── example-server
│   ├── pom.xml
│   └── src
├── example-test
│   ├── pom.xml
│   └── src
├── Jenkinsfile
├── README.md
├── .gitignore
└── pom.xml

完成模板工程的搭建后,需要在模板工程的最外層 pom 文件加入以下配置

<build>  
    <pluginManagement>  
        <plugins>  
            <plugin>  
                <groupId>org.apache.maven.plugins</groupId>  
                <artifactId>maven-archetype-plugin</artifactId>  
                <version>3.0.1</version>  
            </plugin>  
            <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>  
            <plugin>  
                <groupId>org.apache.maven.plugins</groupId>  
                <artifactId>maven-resources-plugin</artifactId>  
                <version>3.0.2</version>
                <configuration>  
                    <encoding>UTF-8</encoding>  
                </configuration>  
            </plugin>  
        </plugins>  
    </pluginManagement>  
</build>

完成之后在根目錄下執行

mvn archetype:create-from-project

刷新項目后,會發現在 ./target/generated-sources/archetype目錄下生成了腳手架工程,生成的腳手架工程可以當成是一個獨立的項目,目錄結構如下圖

.
├── pom.xml
├── src
│   ├── main
│   │   └── resources
│   │       ├── META-INF
│   │       │   └── maven
│   │       │       └── archetype-metadata.xml
│   │       └── archetype-resources
│   │           ├── Jenkinsfile
│   │           ├── README.md
│   │           ├── __artifactId__.iml
│   │           ├── __rootArtifactId__-client
│   │           │   ├── __parentArtifactId__-client.iml
│   │           │   ├── pom.xml
│   │           │   └── src
│   │           ├── __rootArtifactId__-core
│   │           │   ├── __parentArtifactId__-core.iml
│   │           │   ├── pom.xml
│   │           │   └── src
│   │           ├── __rootArtifactId__-server
│   │           │   ├── __parentArtifactId__-server.iml
│   │           │   ├── pom.xml
│   │           │   └── src
│   │           ├── __rootArtifactId__-test
│   │           │   ├── __parentArtifactId__-test.iml
│   │           │   ├── pom.xml
│   │           │   └── src
│   │           └── pom.xml
│   └── test
│       └── resources
│           └── projects
│               └── basic
│                   ├── archetype.properties
│                   └── goal.txt

在腳手架工程目錄下執行 mvn install 就完成了腳手架的本地安裝,安裝完成之后,這個腳手架在本地就可以使用了
可以執行以下腳本來通過此腳手架創建項目

mvn archetype:generate -DgroupId=com.xxx.example -DartifactId=xxxx -Dpackage=com.xxx.example -DarchetypeGroupId=com.demo.archetype -DarchetypeArtifactId=demo-archetype -DarchetypeVersion=1.0.0-SNAPSHOT -DinteractiveMode=false

掃坑

不過如果我們直接這樣使用的話,會發現生成了很多我們並不想要它出現的文件,比如 .idea .iml 文件等等,並且 .gitignore 文件也詭異的消失了(不知為何會忽略這個文件??)... 這顯然不是成熟的腳手架了。那么就需要對它做一些額外的配置了

有兩種方式可以解決上面出現的問題

  1. .gitignore文件重命名為 __gitignore__,然后在模板工程根目錄下新建 archetype.properties 文件,並填入以下內容
## generate for archetype-metadata.xml
excludePatterns=archetype.properties,*.iml,.idea/,.idea/libraries,logs/,build.sh
## generate .gitignore file
gitignore=.gitignore

完成上述配置后,重新執行 mvn archetype:create-from-project 生成腳手架工程。再完成本地安裝,上面出現的問題就會解決

  1. 第二種方式本質上和第一種方式是一樣的,只是第二種方式是直接修改腳手架工程的配置文件。第一種方式相當於是執行  mvn archetype:create-from-project 時讀取了 archetype.properties 幫我們做了配置文件的修改。

maven的腳手架工程下有兩個重要的配置文件

  • ./src/test/resources/projects/basic/archetype.properties

    • 這里可以加入自定義變量,如  gitignore 變量
  • ./src/main/resources/META-INF/maven/archetype-metadata.xml

下面是一個典型的archetype-metadata.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd" name="example"
    xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <requiredProperties>
    <requiredProperty key="gitignore">
      <defaultValue>.gitignore</defaultValue>
    </requiredProperty>
    <requiredProperty key="port">
      <defaultValue>8888</defaultValue>
    </requiredProperty>
  </requiredProperties>
  <fileSets>
    <fileSet encoding="UTF-8" filtered="true">
      <directory></directory>
      <includes>
        <include>__gitignore__</include>
        <include>README.md</include>
        <include>Jenkinsfile</include>
        <include>pom.xml</include>
      </includes>
    </fileSet>
  </fileSets>
  <modules>
    <module id="${rootArtifactId}-client" dir="__rootArtifactId__-client" name="${rootArtifactId}-client">
      <fileSets>
        <fileSet filtered="true" packaged="true" encoding="UTF-8">
          <directory>src/main/java</directory>
          <includes>
            <include>**/*.java</include>
          </includes>
        </fileSet>
      </fileSets>
    </module>
    <module id="${rootArtifactId}-core" dir="__rootArtifactId__-core" name="${rootArtifactId}-core">
      <fileSets>
        <fileSet filtered="true" packaged="true" encoding="UTF-8">
          <directory>src/main/java</directory>
          <includes>
            <include>**/*.java</include>
          </includes>
        </fileSet>
        <fileSet filtered="true" encoding="UTF-8">
          <directory>src/main/resources</directory>
          <includes>
            <include>**/*.xml</include>
          </includes>
        </fileSet>
      </fileSets>
    </module>
    <module id="${rootArtifactId}-server" dir="__rootArtifactId__-server" name="${rootArtifactId}-server">
      <fileSets>
        <fileSet filtered="true" packaged="true" encoding="UTF-8">
          <directory>src/main/java</directory>
          <includes>
            <include>**/*.java</include>
          </includes>
        </fileSet>
        <fileSet filtered="true" encoding="UTF-8">
          <directory>src/main/resources</directory>
          <includes>
            <include>**/*.xml</include>
          </includes>
        </fileSet>
        <fileSet filtered="true" encoding="UTF-8">
          <directory>src/main/resources/META-INF/dubbo</directory>
          <includes>
            <include>*</include>
          </includes>
        </fileSet>
        <fileSet filtered="true" encoding="UTF-8">
          <directory>src/main/resources</directory>
          <includes>
            <include>**/*.yml</include>
          </includes>
        </fileSet>
      </fileSets>
    </module>
    <module id="${rootArtifactId}-test" dir="__rootArtifactId__-test" name="${rootArtifactId}-test">
      <fileSets>
      </fileSets>
    </module>
  </modules>
</archetype-descriptor>

archetype-metadata.xml 結構

簡單介紹archetype-metadata.xml文件的基本結構

  • <requiredProperties>是屬性變量定義層,在這里定義的變量可以在archetype工程文件中通過 ${xxx} 來進行引用,文件名則可以通過 __xxx__來引用變量(這就是為什么要把.gitignore重命名為__gitignore__)。變量在執行 mvn archetype:generate時才錄入真正內容
  • 再往下其實就是定義將要生成的工程目錄結構,首先是一個 fileSets (包含多個 fileSet標簽)標簽定義了根目錄需要生成哪些文件,再通過多個 modules 標簽來定義多個子模塊(如果是多模塊工程的話)。這其中比較重要的其實還是 fileSet標簽,fileSet有兩個重要的屬性
    • filtered = true 如果為true,則該 fileSet包含的文件中的 ${} 占位符會被替換成相應的變量
    • packaged = true 如果為true,則 src/main/java 下得文件內容會被加入 指定包路徑下

總結

一個優秀少坑的腳手架還是能極大的提升生產力的,畢竟這種重復且無價值的勞動我們還是交給工具吧


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM