写在前面

开发新项目就需要搭建新工程,但是搭建新工程的这个过程是非常繁琐浪费时间的,并且不可避免的需要踩坑。更可怕的是,如果是在一个团队中,每新起一个项目都由不同的开发人员去自定义的搭建工程结构,那么对后续的统一管理,监控,运维简直是灾难。基于以上几点,团队内部其实是非常有必要搭建一个统一的脚手架来供统一使用

制作一个脚手架

下面我们就来详细的介绍如何搭建一个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 下得文件内容会被加入 指定包路径下

总结

一个优秀少坑的脚手架还是能极大的提升生产力的,毕竟这种重复且无价值的劳动我们还是交给工具吧

开发一个maven脚手架的更多相关文章

  1. 开发一个 Parcel-vue 脚手架工具

    前言 像我们熟悉的 vue-cli,create-react-app 等脚手架,只需要输入简单的命令 vue init webpack project,即可快速帮我们生成一个初始项目.在实际工作中,我 ...

  2. 如何开发一个maven插件

    maven是当下最流行的项目管理工具,其丰富的插件为我们的工作带来了很大的便利. 但是在一些情况下,开源的插件并不能完全满足我们的需求,我们需要自己创建插件,本文就从0开始带大家一起创建自己的插件. ...

  3. 基于IDEA Plugin插件开发,撸一个DDD脚手架

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 最近很感兴趣结合 IDEA Plugin 开发能力,扩展各项功能.也基于此使用不同的案例,探索 ...

  4. spring-boot+spring-cloud+maven-module 一个 maven多模块的微服务架构模版

    spring-boot-cloud-module spring-boot+spring-cloud+maven-module 一个 maven多模块的微服务架构模版. 新手上路的绝佳模版,只有必要的配 ...

  5. MAVEN学习-第一个Maven项目的构建

    MAVEN安装成功之后就可以进行项目的构建和管理了: 为什么要用maven进行项目的构建和管理? 对于初学者来说一个最直接的也是最容易里的优点在于JAR包的管理,相对于以前开发一个项目的时候我们需要用 ...

  6. Eclipse中一个Maven工程的目录结构

    在之前的javaSE开发中,没有很关注Eclipse工程目录下的环境,总是看见一个src就点进去新建一个包再写一个class.以后的日子中也没有机会注意到一个工程到底是怎么组织的这种问题,跟不要说自己 ...

  7. 【niubi-job——一个分布式的任务调度框架】----如何开发一个niubi-job的定时任务

    引言 上篇文章LZ主要讲解了niubi-job如何安装,如果看过上一篇文章的话,大家应该知道,niubi-job执行的任务是需要用户自己上传jar包的. 那么问题来了,这个jar包如何产生?有没有要求 ...

  8. web项目环境搭建(1):建立一个maven项目

    一.maven简介以及常用概念 1.Maven是一个项目管理和整合的工具.Maven为开发者提供了一套完整的构建生命周期框架.开发团队基本不用花多少时间就能自动完成工程的基础构建配置,因为Maven使 ...

  9. JavaEE开发使用Maven管理的SpringMVC工程

    前几篇博客已经陆陆续续的聊了一些Spring的东西,今天博客我们就来聊一下SpringMVC.SpringMVC目前在JavaEE开发中可谓占据一席之地,用起来也是比较顺手的.低耦合,高内聚,利用一些 ...

随机推荐

  1. SpringCloud-Bus 消息总线

    概述 基本介绍 Spring Cloud Bus 目前支持两种消息代理:RabbitMQ.Kafka Spring Cloud Config 配合 Spring Cloud Bus 使用可以实现配置的 ...

  2. pytorch实现MLP并在MNIST数据集上验证

    写在前面 由于MLP的实现框架已经非常完善,网上搜到的代码大都大同小异,而且MLP的实现是deeplearning学习过程中较为基础的一个实验.因此完全可以找一份源码以参考,重点在于照着源码手敲一遍, ...

  3. JavaScript中一种全新的数据类型-symbol

    连续连载了几篇<ES6对xxx的扩展>,本节咱们换换口味,介绍一种全新的数据类型:Symbol,中文意思为:标志,记号.音标:[ˈsɪmbəl]. 数据类型 在介绍Symbol之前,我们简 ...

  4. springboot+dubbo简单分布式RPC调用demo

    使用springboot+dubbo搭建RPC入门案例 本文背景简述: 最近在学习公司的一套RPC框架,初步接触的时候感觉挺复杂的.但是知道其原理肯定是和dubbo很相似的,毕竟都是RPC框架嘛,只是 ...

  5. GIT分布式版本控制

    1.1Git简介 linus 用C语言编写 2005年诞生 分布式版本管理系统 速度快,适合大规模,跨地区多人协同开发 Git不仅是一款开源的分布式版本控制系统,而且有其独特的功能特性,例如大多数的分 ...

  6. 如何在linux服务器下快速安装配置Node.js

    简单粗暴,先用xshell或其他软件连接服务器 1.下载(此处版本根据官网版本自己修改) wget https://npm.taobao.org/mirrors/node/v8.9.3/node-v8 ...

  7. 使用 kind 快速搭建 kubernetes 环境

    使用 kind 快速搭建 Kubernetes 环境 Intro kind(Kubernetes IN Docker) 是一个基于 docker 构建 Kubernetes 集群的工具,非常适合用来在 ...

  8. libevent(十三)evhttp事件处理流程

    在libevent(六)http server中,作为一个单线程http server,不仅要监听每个连接的到来,还要监听每个连接上的I/O事件. 查看源码可知,在evhttp_bind_socket ...

  9. D. Ehab the Xorcist(纯构造方法)

    \(如果觉得下面难以理解,可以去这里看一种较为简单的解法\):saf \(这个题嘛,首先要明确异或的性质:相同为0,不同为1.\) \(举个例子,我们来构造u=15和v=127的情况\) \(注意到, ...

  10. Nodejs异步编程

    异步函数:异步函数是异步编程语法的终极解决方案,它可以把异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得更清晰. const fn = async () =>{}; async  f ...