手寫Maven的archetype項目腳手架

1、背景

  maven是一個很好的代碼構建工具,採用「約定優先於配置」的原則進行項目管理,相信不少的java開發者應該都瞭解maven並可能在工做當中都是經過maven來管理項目的,在建立的項目的時候,咱們每每會使用maven內置的項目骨架也就是archetype來快速生成項目結構。可是在一個團隊作開發的過程當中,可能僅僅依靠maven預先提供的archetyp多是不夠的,團隊之間協做有本身的定義方式,每一個人的結構定義風格也不盡相同,在這樣的背景下咱們有必要去定義一個統一的代碼骨架供團隊使用,這樣作的好處是當團隊須要開始一個新項目的時候,能夠利用自定義的maven骨架一鍵生成項目。java

  archetype是在maven-archetype-plugin插件執行generate目標的時候進行配置的,咱們常用到maven的內嵌的骨架包括:maven-archetype-webapp、maven-archetype-quickstart。前者用來快速搭建一個web工程項目,後者用來快速搭建一個普通的java工程項目。git

2、手寫普通單模塊項目的archetype

單模塊項目的archetype腳手架項目的結構github

  

上圖中的各個文件詳解:web

  • 根目錄beast-archetype下的pom.xml和通常的maven項目同樣主要定義archetype項目的座標等信息。
  • 全部的項目骨架內容都集中在src/main/resources/archetype-resources文件夾下。
  • archetype-resources中的pom.xml定義了待生成項目的pom文件的內容,/src/main/java、/src/test/java中分別定義了待生成項目中相應目錄下的內容
  • /src/main/resources/META-INF/maven/archetype-metadata.xml中定義相關的元數據描述(其中該文件的位置固定爲resources/META-INF/maven文件夾下,且名稱固定爲archetype-metadata.xml)。

1.beast-archetype/pom.xml內容以下apache

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.thebeastshop</groupId>
    <artifactId>beast-archetype</artifactId>
    <version>1.1</version>
    <packaging>jar</packaging>

    <name>beast-archetype</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>beast-archetype</finalName>
    </build>
</project>

2.src/main/resources/archetype-resources/pom.xml內容以下:api

<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
            http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>${groupId}</groupId>
    <artifactId>${artifactId}</artifactId>
    <version>${version}</version>
    <name>${artifactId}</name>
    
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
             <plugin> 
                 <artifactId>maven-deploy-plugin</artifactId> 
                 <configuration> 
                    <skip>true</skip> 
                 </configuration> 
             </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-archetype-plugin</artifactId>
                    <version>2.2</version>
                    <configuration>
                        <source>1.7</source>
                        <target>1.7</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-source-plugin</artifactId>
                    <configuration>
                        <encoding>UTF-8</encoding>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

其中:上面${}標識的變量都是經過maven中的命令行傳進來的,如:mvn archetype:generate -DgroupId=com.thebeastshopmybatis

3.src/main/resources/META-INF/maven/archetype-metadata.xml內容以下:app

<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor  name="beast-archetype"
        xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        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">

    <requiredProperties>
        <requiredProperty key="package-name" />
    </requiredProperties>

    <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>**/*.*</include>
            </includes>
        </fileSet>
        <fileSet filtered="true" packaged="true" encoding="UTF-8">
            <directory>src/test/java</directory>
            <includes>
                <include>**/*.java</include>
            </includes>
        </fileSet>
        <fileSet encoding="UTF-8">
            <directory>src/test/resources</directory>
            <includes>
                <include>**/*.*</include>
            </includes>
        </fileSet>
    </fileSets>
</archetype-descriptor>

說明:webapp

  • packaged="true"標識src/main/resources/archetype-resources/src/main/java中對應的內容是否要放入到package中,好比package爲com.thebeastshop,那麼若是該屬性爲true,則對應的java文件會放到com/thebeastshop文件夾下,也就是包路徑下。
  • filtered="true"標識下面提到的${}是否要進行替換

4.src/main/resources/archetype-resources/src/main/java/Demo.java內容以下:maven

package ${package};

public class Demo{
    public static void main( String[] args )
    {
        System.out.println( "Hello My Archetype!" );
    }
}

5.這樣咱們就手寫好了一個自定義的maven的archetype骨架項目,咱們只須要經過mvn clean install 命令把該jar包安裝到本地倉庫,而後經過本地倉庫中的該jar包來生成一個項目看看效果,使用以下命令:

 mvn archetype:generate 
  -DgroupId=comthebeastshop
  -DartifactId=beast-test
  -Dpackage="com.thebeastshop.test"
  -DarchetypeGroupId=com.thebeastshop
  -DarchetypeArtifactId=beast-archetype -DarchetypeVersion=1.1 -X -DarchetypeCatalog=local

3、手寫maven多module的項目骨架archetype

1.多模塊骨架項目的項目結構

這跟單模塊項目區別不大,可是有幾個概念須要說明:

  • 「__rootArtifactId__」佔位符會被parent項目的artifactId替換
  • ${rootArtifactId}也會被parent項目的artifactId替換
  • src/main/resources/archetype-resources裏必需要有一個頂級pom文件(若是是單工程就是工程pom文件),同時子文件夾表明了模塊定義

2.模板工程定義描述文件:META-INF/maven/archetype-metadata.xml

<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor  name="beast-archetype"
        xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        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">

    <requiredProperties>
        <requiredProperty key="groupId">
            <defaultValue>com.thebeastshop</defaultValue>
        </requiredProperty>
        <requiredProperty key="artifactId">
            <defaultValue>test</defaultValue>
        </requiredProperty>
        <requiredProperty key="package">
            <defaultValue>com.thebeastshop.test</defaultValue>
        </requiredProperty>
    </requiredProperties>

    <modules>
        <module id="${rootArtifactId}-api" name="${rootArtifactId}-api" dir="__rootArtifactId__-api">
            <fileSets>
                <fileSet filtered="true" encoding="UTF-8" packaged="true">
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet filtered="true" encoding="UTF-8" packaged="true">
                    <directory>src/test/java</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet encoding="UTF-8">
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet encoding="UTF-8">
                    <directory>src/test/resources</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
            </fileSets>
        </module>
        <module id="${rootArtifactId}-core" name="${rootArtifactId}-core" dir="__rootArtifactId__-core">
            <fileSets>
                <fileSet filtered="true" encoding="UTF-8" packaged="true">
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet filtered="true" encoding="UTF-8" packaged="true">
                    <directory>src/test/java</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet filtered="true" encoding="UTF-8">
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet encoding="UTF-8">
                    <directory>src/test/resources</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
            </fileSets>
        </module>
        <module id="${rootArtifactId}-dao" name="${rootArtifactId}-dao" dir="__rootArtifactId__-dao">
            <fileSets>
                <fileSet filtered="true" encoding="UTF-8" packaged="true">
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet filtered="true" encoding="UTF-8" packaged="true">
                    <directory>src/test/java</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet filtered="true" encoding="UTF-8">
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>**/*.*</include>
                        <include>mapper</include>
                    </includes>
                </fileSet>
                <fileSet encoding="UTF-8">
                    <directory>src/test/resources</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
            </fileSets>
        </module>
        <module id="${rootArtifactId}-main" name="${rootArtifactId}-main" dir="__rootArtifactId__-main">
            <fileSets>
                <fileSet filtered="true" encoding="UTF-8" packaged="true">
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet filtered="true" encoding="UTF-8" packaged="true">
                    <directory>src/test/java</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet filtered="true" encoding="UTF-8">
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet encoding="UTF-8">
                    <directory>src/test/resources</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet encoding="UTF-8">
                    <directory>src/main/assembly</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet encoding="UTF-8">
                    <directory>src/main/bin</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
            </fileSets>
        </module>
        <module id="${rootArtifactId}-mybatisGen" name="${rootArtifactId}-mybatisGen" dir="__rootArtifactId__-mybatisGen">
            <fileSets>
                <fileSet filtered="true" encoding="UTF-8" packaged="true">
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet filtered="true" encoding="UTF-8" packaged="true">
                    <directory>src/test/java</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet encoding="UTF-8">
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
                <fileSet encoding="UTF-8">
                    <directory>src/test/resources</directory>
                    <includes>
                        <include>**/*.*</include>
                    </includes>
                </fileSet>
            </fileSets>
        </module>
    </modules>
</archetype-descriptor>
  • 屬性變量定義
  • <requiredProperties>
        <requiredProperty key="groupId">
            <defaultValue>com.thebeastshop</defaultValue>
        </requiredProperty>
        <requiredProperty key="artifactId">
            <defaultValue>test</defaultValue>
        </requiredProperty>
        <requiredProperty key="package">
            <defaultValue>com.thebeastshop.test</defaultValue>
        </requiredProperty>
    </requiredProperties>

    這些屬性能夠在資源元文件裏的任意一個文件裏經過${var}來引用,因此的元文件最終均可以選擇經過velocity引擎來執行替換後生成。
    默認的屬性有:groupId,artifactId,packeage,version等

  • 項目子模塊定義
    <modules>
        <module id="${rootArtifactId}-api" name="${rootArtifactId}-api" dir="__rootArtifactId__-api">
            ...
        </module>
        <module id="${rootArtifactId}-core" name="${rootArtifactId}-core" dir="__rootArtifactId__-core">
            ...
        </module>
        <module id="${rootArtifactId}-dao" name="${rootArtifactId}-dao" dir="__rootArtifactId__-dao">
            ...
        </module>
        <module id="${rootArtifactId}-main" name="${rootArtifactId}-main" dir="__rootArtifactId__-main">
            ...
        </module>
        <module id="${rootArtifactId}-mybatisGen" name="${rootArtifactId}-mybatisGen" dir="__rootArtifactId__-mybatisGen">
            ...
        </module>
    </modules>

    module有三個屬性,解釋以下:
    id     :定義子模塊工程的artifactId.
    dir    :子模塊工程源文件在archetype-resources裏對應的directory.
    name   :子模塊的名字.

3.子模塊pom.xml定義以下(以core模塊爲例):

<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
            http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.thebeastshop</groupId>
        <artifactId>${rootArtifactId}</artifactId>
        <version>${version}</version>
    </parent>

    <artifactId>${artifactId}</artifactId>
    <name>${artifactId}</name>
    
    <dependencies>
        <dependency>
            <groupId>com.thebeastshop</groupId>
            <artifactId>${rootArtifactId}-api</artifactId>
            <version>${api.version}</version>
        </dependency>
        <dependency>
            <groupId>com.thebeastshop</groupId>
            <artifactId>${rootArtifactId}-dao</artifactId>
            <version>${project.parent.version}</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
             <plugin> 
                 <artifactId>maven-deploy-plugin</artifactId> 
                 <configuration> 
                    <skip>true</skip> 
                 </configuration> 
             </plugin>
        </plugins>
    </build>
</project>

其中${rootArtifactId}就表明父項目的artifactId.

4.咱們和單模塊腳手架工程同樣,經過mvn clean install命令把該腳手架項目安裝到本地maven倉庫,而後就可使用該項目來快速生成新項目結構了,生成命令以下:

mvn archetype:generate 
  -DgroupId=com.thebeastshop
  -DartifactId=ddd
  -Dversion=1.0.0-SNAPSHOT
  -DarchetypeGroupId=com.thebeastshop
  -DarchetypeArtifactId=beast-archetype
  -DarchetypeVersion=1.3-SNAPSHOT -X -DarchetypeCatalog=local

咱們就會看到生成好的項目結構以下:

多模塊項目腳手架源碼:https://github.com/hafizzhang/beast-archetype

4、總結

  在工做中,咱們一般要有「偷懶」意識,經過摸索來開發出相似項目腳手架同樣的工具來提高本身工做的效率。不能成天都是渾渾噩噩的過去,並且表面上看上去很難的東西實際上並不見得必定就如想象中的難。程序猿仍是要有所追求,哈哈~

相關文章
相關標籤/搜索