生成脚手架
随着新框架的不断稳定(同时也带来了不错的收益),新的项目以及重构项目不断的往新框架上切,基于这个原因,要把新框架整一个脚手架。
脚手架中包含了demo(为了学习而框架,实际开发中会有一些便利性的调整)
注意事项
-
依赖maven环境,必须配置MVAVA_HOME
-
依赖jdk环境(一定要jdk,不要jre)
-
maven-archetype 的模板使用velocity
引入插件以及自定义配置文件
先找一个可以跑起来的demo,在pom文件中引入脚手架的maven plugin 我的工程结构如下:
项目地址:https://github.com/yxkong/ddd-framework/tree/main/ddd-demo
基于ddd应用框架写的demo
-
adapter 适配器层
-
application 应用层
-
domain 领域层
-
infrastructure 基础设施层
我们的项目结构
在demo的pom文件中引入
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-archetype-plugin</artifactId>
</plugin>
maven-archetype-plugin工作流程如下: 具体使用请看这里: http://maven.apache.org/archetype/maven-archetype-plugin/
自定义 archetype.properties
package=com.yxkong.demo
version=1.0
groupId=com.yxkong
artifactId=ddd-demo
# 需要忽略的文件,不会打包进去
excludePatterns=/**/*.iml,/.idea/**/*,/logs,/target
# 需要采用template解析和替换本配置文件定义的参数的文件
archetype.filteredExtensions=java,sql,yml,xml,properties,factories,ftl
# 自定义参数,自定义的参数在模板中可以使用
appName=demo
upperAppName=Demo
webPort=8081
author=yxkong
命令生成脚手架
在ddd-demo项目中执行以下命令
指定setting(我本地使用了两套配置,所以我通过-s指定指定了)
mvn clean archetype:create-from-project -Darchetype.properties=archetype.properties -s /Users/yxk/javaServer/maven/apache-maven-3.6.3/conf/settings-aliyun.xml
指定以archetype.properties
mvn clean archetype:create-from-project -Darchetype.properties=archetype.properties
如果没有自定义参数可以直接执行以下命令,都是使用的默认mvn
mvn archetype:create-from-project
执行完命令后,会在target目录下生成generated-sources目录资源
脚手架模板处理
新建一个空项目ddd-archetype,将target目录中generated-sources 拷贝进去
基本框架修改
修改成自己想定义的框架的groupId、artifactId、version,在生成代码时引用的archetype*相关参数都是从这里来的。
ddd-archetype/pom.xml
<groupId>com.yxkong</groupId>
<artifactId>ddd-archetype</artifactId>
<version>0.1</version>
<packaging>maven-archetype</packaging>
<name>ddd-archetype</name>
自定义属性 custom.properties
#set( $appName = ${package} )
#if(${package.indexOf(".")}!=-1)
#set( $cc = ${package.split(".")})
#if($cc != $null && ${cc.size()} > 0)
#set( $lastIndex = $cc.size() - 1 )
#set( $$appName = $cc[$lastIndex] )
#end
#end
#set( $upperAppName = ${appName}.substring(0).toUpperCase() )
个性化修改
要想个性化修改,我们必须知道一些基本规则:
在文件中通过${变量名} 去替换
在路径中通过__变量名__ 去替换
已有变量如下:
-
- appName 应用名称首字母小写 通过 mvn archetype:generate 注入
- upperAppName 应用名称首字符大写 通过 mvn archetype:generate 注入
- webPort 应用启动端口 通过 mvn archetype:generate 注入
- author author 通过 mvn archetype:generate 注入
- dbName 数据库名 通过 mvn archetype:generate 注入
- package 要生成的报名,通过 mvn archetype:generate 注入
- groupId 要生成的groupId 通过 mvn archetype:generate 注入
- artifactId 要生成的artifactId (每个模块中的不一样,依赖于mavne的结构)
- version 要生成的版本号 通过 mvn archetype:generate 注入
- rootArtifactId parent中的 artifactId
- rootGroupId parent中的 artifactId 一般全局一样
在这里我一些需求,每次我生成的demo,需要加上模块前缀 比如:我生成一个user-ddd的项目,内部结构需要如下:
user-ddd
- user-adapter
- com.yxkong
- UserStater.java
- com.yxkong.user.adapter
- user-application
- com.yxkong.user.application
- user-domain
- com.yxkong.user.domain
- user-infrastructure
- com.yxkong.user.infrastructure
修改的地方:
-
模块名前面都加__appName__-模块名
-
模块内都是 package.模块名
-
类中的引用都用package替换
重点是这里 src/main/resources/META-INF/maven/archetype-metadata.xml
<modules>
# dir 要注意,一定要和项目中的真实目录一样(变量不会解析),在生成时,会去对应的目录里copy模板,然后生成新的项目
# id 和 name都是要生成的模块名称
<module id="${appName}-adapter" dir="__appName__-adapter" name="${appName}-adapter">
</modules>
生成archetype-catalog 与上传
所有的地方调整完以后执行,在该项目中执行
mvn clean install
会在本地的仓库中生产archetype-catalog.xml,内容就是ddd-archetype/pom.xml 中定义的
<?xml version="1.0" encoding="UTF-8"?>
<archetype-catalog xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-catalog/1.0.0 http://maven.apache.org/xsd/archetype-catalog-1.0.0.xsd"
xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-catalog/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<archetypes>
<archetype>
<groupId>com.yxkong</groupId>
<artifactId>ddd-archetype</artifactId>
<version>0.1</version>
<description>Parent pom providing dependency and plugin management for applications built with Maven</description>
</archetype>
</archetypes>
</archetype-catalog>
上传远程服务器
mvn deploy
通过脚手架生成项目
找一个空目录执行以下命令,切记、切记、切记
mvn archetype:generate -DarchetypeGroupId=com.yxkong -DarchetypeArtifactId=ddd-archetype -DarchetypeVersion=0.1 -DgroupId=com.yxkong -DartifactId=user-ddd -Dpackage=com.yxkong.user -Dversion=1.0 -DappName=user -DupperAppName=User -X -DarchetypeCatelog=local -s /Users/yxk/javaServer/maven/apache-maven-3.6.3/conf/settings-aliyun.xml
如果报以下错误:说明执行 generate命令的时候当前目录有一个pom文件
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-archetype-plugin:3.2.0:generate (default-cli) on project ddd-archetype: Unable to add module to the current project as it is not of packaging type 'pom' -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-archetype-plugin:3.2.0:generate (default-cli) on project ddd-archetype: Unable to add module to the current project as it is not of packaging type 'pom'
生成后的项目目录如下:
修改后的archetype-metadata.xml
<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor xsi:schemaLocation="https://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.1.0 http://maven.apache.org/xsd/archetype-descriptor-1.1.0.xsd" name="ddd-archetype"
xmlns="https://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<requiredProperties>
<requiredProperty key="appName">
<defaultValue>demo</defaultValue>
</requiredProperty>
<requiredProperty key="upperAppName">
<defaultValue>Demo</defaultValue>
</requiredProperty>
<requiredProperty key="author">
<defaultValue>yxkong</defaultValue>
</requiredProperty>
<requiredProperty key="webPort">
<defaultValue>8001</defaultValue>
</requiredProperty>
<requiredProperty key="dbName">
<defaultValue>user</defaultValue>
</requiredProperty>
</requiredProperties>
<fileSets>
<fileSet filtered="true" encoding="UTF-8">
<directory>doc/init</directory>
<includes>
<include>**/*.sql</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>doc</directory>
<includes>
<include>**/*.yml</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>doc/nacos</directory>
<includes>
<include>**/*.properties</include>
</includes>
</fileSet>
<fileSet encoding="UTF-8">
<directory>doc/conf</directory>
<includes>
<include>**/*.log</include>
<include>**/*.cnf</include>
<include>**/*.conf</include>
</includes>
</fileSet>
<fileSet encoding="UTF-8">
<directory>ssh</directory>
<includes>
<include>**/*.sh</include>
</includes>
</fileSet>
<fileSet encoding="UTF-8">
<directory>doc</directory>
<includes>
<include>**/*.png</include>
</includes>
</fileSet>
<fileSet encoding="UTF-8">
<directory>doc/nacos</directory>
<includes>
<include>**/*.env</include>
</includes>
</fileSet>
<fileSet encoding="UTF-8">
<directory></directory>
<includes>
<include>readme.md</include>
<include>.gitignore</include>
</includes>
</fileSet>
</fileSets>
<modules>
<!--
dir 是真实的目录,是什么就是什么,不会解析,在生成的时候从这个目录里获取模板
id 和name 都是要生成的模块名称
-->
<module id="${appName}-adapter" dir="__appName__-adapter" name="${appName}-adapter">
<fileSets>
<!-- 不要加packaged="true" ,加了会在对应的directory中添加package包-->
<fileSet filtered="true" encoding="UTF-8">
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
<include>**/*.gitkeep</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>src/main/resources</directory>
<includes>
<include>**/*.yml</include>
</includes>
</fileSet>
<fileSet encoding="UTF-8">
<directory></directory>
<includes>
<include>.gitignore</include>
</includes>
</fileSet>
</fileSets>
</module>
<module id="${appName}-application" dir="__appName__-application" name="${appName}-application">
<fileSets>
<fileSet filtered="true" packaged="true" encoding="UTF-8">
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
<include>**/*.gitkeep</include>
</includes>
</fileSet>
<fileSet encoding="UTF-8">
<directory></directory>
<includes>
<include>.gitignore</include>
</includes>
</fileSet>
</fileSets>
</module>
<module id="${appName}-infrastructure" dir="__appName__-infrastructure" name="${appName}-infrastructure">
<fileSets>
<fileSet filtered="true" packaged="true" encoding="UTF-8">
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
<include>**/*.gitkeep</include>
</includes>
</fileSet>
<fileSet filtered="true" encoding="UTF-8">
<directory>src/main/resources</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.xml</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></directory>
<includes>
<include>.gitignore</include>
</includes>
</fileSet>
</fileSets>
</module>
<module id="${appName}-domain" dir="__appName__-domain" name="${appName}-domain">
<fileSets>
<fileSet filtered="true" packaged="true" encoding="UTF-8">
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
<include>**/*.gitkeep</include>
</includes>
</fileSet>
<fileSet encoding="UTF-8">
<directory></directory>
<includes>
<include>.gitignore</include>
</includes>
</fileSet>
</fileSets>
</module>
</modules>
</archetype-descriptor>
src/main/resources/archetype-resources/pom.xml
<?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>
<parent>
<groupId>com.yxkong</groupId>
<artifactId>ddd-parent</artifactId>
<version>0.1</version>
</parent>
<artifactId>${artifactId}</artifactId>
<groupId>${groupId}</groupId>
<packaging>pom</packaging>
<version>${version}</version>
<modules>
<module>${appName}-adapter</module>
<module>${appName}-application</module>
<module>${appName}-infrastructure</module>
<module>${appName}-domain</module>
</modules>
<properties>
<argLine>-Dfile.encoding=UTF-8</argLine>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${groupId}</groupId>
<artifactId>${appName}-adapter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${groupId}</groupId>
<artifactId>${appName}-application</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${groupId}</groupId>
<artifactId>${appName}-infrastructure</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${groupId}</groupId>
<artifactId>${appName}-domain</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 配置远程仓库 -->
<distributionManagement>
<repository>
<id>aliyun</id>
<url>https://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
</distributionManagement>
<repositories>
<repository>
<id>aliyun-public</id>
<name>aliyun-public</name>
<url>https://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<build>
<defaultGoal>compile</defaultGoal>
<finalName>${project.artifactId}-${project.version}</finalName>
<plugins>
<!-- 编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<!--屏蔽test-->
<skip>true</skip>
<!--传递额外的编译参数-->
<compilerArgs>
<arg>-verbose</arg>
<!-- <arg>-Xlint:all,-options,-path</arg>-->
<arg>-Xlint:unchecked</arg>
<arg>-Xlint:deprecation</arg>
<!--添加一些jar,让bootstrap ClassLoader加载-->
<!-- <arg>-Xbootclasspath:${java.home}/lib/rt.jar${path.separator}${java.home}/lib/jce.jar</arg>-->
<!--解决本地jar包依赖问题-->
<!-- <arg>-Xextdirs:${basedir}\lib</arg>-->
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<!--防止将.gitignore文件忽略-->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<addDefaultExcludes>false</addDefaultExcludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-archetype-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
http://maven.apache.org/archetype/maven-archetype-plugin/
mvn archetype:generate 参数说明:
-DarchetypeGroupId=com.yxkong 脚手架的groupId
-DarchetypeArtifactId=ddd-archetype 脚手架的artifactId
-DarchetypeVersion=0.1 脚手架版本
-DgroupId=com.xxx 需要生成的项目groupId
-DartifactId=demo-archetype-generate 需要生成的项目artifactId
-Dversion=1.0.0 需要生成的版本号
-DarchetypeCatalog=internal 使用私有仓库脚手架jar包, 前提:已经把脚手架发布到私有仓库中
remote,远程Maven库中提供的模板。mvn archetype:generate默认使用该类模板
local,本地Maven库中提供的模板。mvn archetype:generate默认使用该类模板,作为remote的补充。Maven初始为空,执行mvn install时会将当前项目加入local模板库
internal,Apache Maven项目默认提供的模板。mvn archetype:generate -DarchetypeCatalog=internal使用该类模板
file://...,给出本地计算机上的一个路径,在该路径下有一个archetype-catalog.xml文件(如果是其他文件名则必须给出),其中配置了模板
-DarchetypeCatalog=local 使用本地脚手架jar包, 如果不配置, 它会到中央仓库去下载, 会导致失败
-X debug模式
整体代码:
https://github.com/yxkong/ddd-framework
在用的过程中可以参考下面