Maven - 自定义archetype

Maven - 自定义archetype

前言

要自定义archetype,首先要了解maven的archetype是做什么的。

试想这样一个问题:当我们要从头创建一个maven工程时,需要做什么?

maven的原则是“约定大于配置”,因此,一个maven工程一定会有一个约定的、默认的目录额结构,如下所示:

a-test-project
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |   `-- resources
    |-- test
    |   `-- java
    |   `-- resources

这些文件和目录难道要一个个手动创建吗?当然不需要!maven archetype就是用来帮我们创建这些东西的。只需要简单地执行一行命令,一个maven工程就生成了。

如:

mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart

这里就用到了maven-archetype-quickstart这样一个archetype。自动生成的目录结构如下所示:

my-app
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- mycompany
    |               `-- app
    |                   `-- App.java
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java

通过官网Introduction to Archetypes中列出了Maven默认提供的一些archetype,如:

  • maven-archetype-quickstart
  • maven-archetype-webapp

有了Maven默认提供的archetype就够了吗?如果我们想在生成project的时候把我们自定义的依赖放到pom.xml文件中怎么办?如果我们生成的project想添加dubbo/spring cloud进去怎么办?

显然,通过Maven提供的archetype是实现不了的。

但是,Maven支持自定义archetype,我们就可以通过自定义的archetype,把我们想生成的东西定义到archetype中,然后自动生成project时,一个命令行就可以搞定所有。

自定义archetype是通过Maven的maven-archetype-archetype这样一个archetype做到的。

官网描述:Maven Archetype Archetype
这里还有一篇国外大佬写的博客,非常不错:Guide to Maven Archetype

通过自定义的archetype,我们可以生成一个单module工程。如果喜欢父子工程这种组织结构,当然也是可以实现的。下面看看如何实现。

核心内容

首先要执行maven-archetype-archetype,生成archetype自定义框架

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-archetype -DarchetypeVersion=1.3 

生成的目录结构如下所示(关于test部分的文件结构省略了):

qijin-quickstart/
├── README.md
├── pom.xml
├── src
│   ├── main
│   │   └── resources
│   │       ├── META-INF
│   │       │   └── maven
│   │       │       └── archetype-metadata.xml
│   │       └── archetype-resources
│   │           ├── pom.xml
│   │           └── src
│   │               ├── main
│   │               │   └── java
│   │               │       └── App.java
│   │               └── test
│   │                   └── java
│   │                       └── AppTest.java
│   └── test

这里面的核心在于src/main/resources/META-INF/maven/archetype-metadata.xml文件,这个是自定义archetype的描述文件。也就是说,你想生成怎样的自定义archetype,都是需要在这个文件中配置的。

关于archetype-metadata.xml文件的配置,可参看官网ArchetypeDescriptor,这里就不做一一解释了。

这里注意,archetype-metadata.xml文件只是定义了文件的复制规则、文件的过滤规则、占位符是否替换等。我们要生成的project,pom.xml文件的内容是怎样的,自动生成哪些目录和文件,是在src/main/resources/archetype-resources中定义的。

│   │       └── archetype-resources
│   │           ├── pom.xml
│   │           └── src
│   │               ├── main
│   │               │   └── java
│   │               │       └── App.java
│   │               └── test
│   │                   └── java
│   │                       └── AppTest.java

看到archetype-resources的目录结构,是不是感到很熟悉?没错,这个就是一个标准的maven目录结构。实际的情况是,默认配置下,archetype-resources目录下的文件内容和目录结构,就是我们要生成project的文件内容和目录结构。因此,archetype-resources下的pom.xml文件,即是最终生成project中的pom.xml文件。这样,我们就可以根据需要,随意在archetype-resources目录下,添加和修改内容了。

我们自定义的archetype写完后,mvn install一下,就像普通的jar包一样,安装到本地仓库了。注意,我们刚才做的所有事情只是自定义了一个archetype,并不是我们最终要生成的工程,我们需要像使用maven-archetype-quickstart一样使用它,才能得到最终的工程。

假设qijin-quickstart/pom.xml(这个文件是通过maven-archetype-archetype生成的)的内容如下所示(请主要关注groupIdartifactId):

<?xml version="1.0" encoding="UTF-8"?>

<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>tech.qijin.archetype</groupId>
    <artifactId>qijin-quickstart</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>maven-archetype</packaging>

    <name>Archetype - archetype</name>

    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>
    <build>
        <extensions>
            <extension>
                <groupId>org.apache.maven.archetype</groupId>
                <artifactId>archetype-packaging</artifactId>
                <version>3.0.1</version>
            </extension>
        </extensions>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-archetype-plugin</artifactId>
                    <version>3.0.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

mvn install命令后,通过如下命令,就可以像使用maven-archetype-quickstart一样,自动生成一个我们想要的工程了:

mvn archetype:generate -DarchetypeGroupId=tech.qijin.archetype -DarchetypeCatalog=local -DarchetypeArtifactId=qijin-multimodules -DarchetypeVersion=1.0-SNAPSHOT 

注:
-DarchetypeCatalog=local的意思是从本地repository查找archetype。如果使用mvn deploy命令将我们自定义的archetype deploy到远程仓库,这个参数可以不要。

单Module

步骤

  1. 执行maven-archetype-archetype,生成archetype自定义框架
  2. 根据需要修改archetype-resources目录下的文件(如只是初步了解,可以不修改)。
  3. 根据需要修改src/main/resources/META-INF/maven/archetype-metadata.xml(如只是初步了解,可以不修改)
  4. 一切完毕后,执行mvn install将自定义的archetype部署到本地repository。
  5. 如果想部署到远程仓库,可以执行mvn deploy
  6. 使用刚生成的archetype生成工程。

在参数中没有指定artifactIdgroupId等参数时,会使用Interactive mode,提示输入这些参数,不输入不会通过,如下提示:

Generating project in Interactive mode
[INFO] Archetype repository not defined. Using the one from [org.apache.maven.archetypes:maven-archetype-archetype:1.3] found in catalog remote
Define value for property 'groupId': Define value for property 'artifactId': Define value for property 'version' 1.0-SNAPSHOT: : Define value for property 'package'

单module实现起来比较简单,通过上面的6个步骤,不用做任何修改,都能跑通所有流程。

但是,在一些工程实践中,通常会用到Maven的多Module模式,也叫父子工程。这种架构的工程也可以通过自定义archetype生成吗?显然,是可以的!

这里有一个我自己写的Demo,可以在此基础上修改后,直接使用:GitHub地址

多Module

多Module中,每个Module的pom.xml文件和目录结构都可能不一样,多个子Module还需要添加到父pom中,这是多Module的关键

顺着这个思路去想,单Module所有文件在archetype-resources中,显然是不够的。需要在这个目录下有多个文件夹。

具体怎么配置,可以参考这几篇博客(写得太累,不想写了,以后再补吧):

关键点在于:

  1. 文件夹使用__rootArtifactId__作为前缀,maven会自动把__rootArtifactId__替换成你写的artifactId。

举个例子:
如果archetype-resources目录下的目录结构是:

|--archetype-resources
|--pom.xml
|--|--__rootArtifactId__-db
|--|--__rootArtifactId__-service

最终通过这个archetype生成的工程时,如果设定的artifactId=account,目录结构会是:

|--pom.xml
|--|--account-db
|--|--account-service

有木有很方便

  1. src/main/resources/META-INF/maven/archetype-metadata.xml文件中添加相应的module模块和定义
<module id="${rootArtifactId}-db" dir="__rootArtifactId__-db" name="${rootArtifactId}-db">
...
</module>
<module id="${rootArtifactId}-server" dir="__rootArtifactId__-server" name="${rootArtifactId}-server">
...
</module>

这里有一个我自己写的Demo,可以在此基础上修改后,直接使用:GitHub地址

修改完成后,使用方法与单Module完全一样,如:

mvn archetype:generate -DarchetypeGroupId=tech.qijin.archetype -DarchetypeCatalog=local -DarchetypeArtifactId=qijin-multimodules -DarchetypeVersion=1.0-SNAPSHOT -DgroupId=tech.qijin.account  -DartifactId=account  -Dversion=1.0.0-SNAPSHOT  -Dpackage=tech.qijin.account
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 简介 概述 Maven 是一个项目管理和整合工具 Maven 为开发者提供了一套完整的构建生命周期框架 Maven...
    闽越布衣阅读 4,208评论 6 39
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,367评论 6 343
  • 本章是《maven实战》最后一章啦,十四章走来,每天都在坚持,同时也简单的记录了自己每一天的点点滴滴,感谢大家支持...
    小炼君阅读 2,764评论 1 50