Maven archetype 原型插件详解

2024-03-15 13:59

本文主要是介绍Maven archetype 原型插件详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原型插件的作用与使用流程

可以理解为是一个助力于生成一个脚手架项目的插件,内部依赖 Velocity 模板引擎。

应用流程:

  1. 根据编写的原型元工程,通过 maven archetype 插件,帮助我们生成一个脚手架工程(原型工程)。
  2. 对脚手架工程(原型工程)进行打包,生成最终的可运行的脚手架工程。
  3. 执行可运行的脚手架工程(期间可输入脚手架定义的参数)即可创建出我们需要的目标项目。

各个阶段的工程结构

1. 原型元工程

原型元工程
pom.xml 中配置原型插件:

<build><plugins><!-- 非必要 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-release-plugin</artifactId><version>2.5.1</version><dependencies><dependency><groupId>org.apache.maven.shared</groupId><artifactId>maven-invoker</artifactId><version>2.2</version></dependency></dependencies></plugin><!-- 必要:原型插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-archetype-plugin</artifactId><version>2.0-alpha-4</version></plugin></plugins>
</build>

2. 原型工程

在原型元工程的 POM 目录下(maven-archetype-test)执行:

mvn archetype:create-from-project

即可在maven-archetype-test/target/generated-sources/archetype 目录下生成原型工程。


注意:原型元工程中的 prv.cqq.mavenarchetype 包层级已经被剔除,切换到了根路径。后面根据可运行的原型工程生成目标项目时,可动态切换为用户输入的设置路径。

原型工程
生成的与 src 目录同级最外层的原型工程的 pom.xml 的内容如下:

注意:原型工程的坐标信息 artifactId 会默认追加 -archetype 后缀

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><modelVersion>4.0.0</modelVersion><groupId>priv.cqq</groupId><!-- 坐标信息中追加了 -archetype 后缀 --><artifactId>maven-archetype-test-archetype</artifactId><version>0.0.1-SNAPSHOT</version><packaging>maven-archetype</packaging><name>maven-archetype-test-archetype</name><build><!-- 自动生成的原型打包插件 --><extensions><extension><groupId>org.apache.maven.archetype</groupId><artifactId>archetype-packaging</artifactId><version>2.0-alpha-4</version></extension></extensions><!-- 打包插件 --><plugins><plugin><artifactId>maven-archetype-plugin</artifactId><version>2.0-alpha-4</version><extensions>true</extensions></plugin></plugins></build>
</project>

3. 可运行的原型工程

在原型工程的 POM 目录下(maven-archetype-test/target/generated-sources/archetype )执行:

mvn install

即可在 target 目录下生成可运行的原型工程:

可运行的原型工程

4. 执行可运行的原型工程生成目标项目

mvn archetype:generate 
-DinteractiveMode=false
-DarchetypeCatalog=local
-DarchetypeGroupId=priv.cqq
-DarchetypeArtifactId=maven-archetype-test-archetype
-DarchetypeVersion=0.0.1-SNAPSHOT
-DgroupId=org.cqq
-DartifactId=targetapp
-Dpackage=org.cqq.targetapp
-Dversion=0.0.1-SNAPSHOT
-DarchetypeCatalog=local

mvn archetype:generate -DinteractiveMode=false -DarchetypeCatalog=local -DarchetypeGroupId=priv.cqq -DarchetypeArtifactId=maven-archetype-test-archetype -DarchetypeVersion=0.0.1-SNAPSHOT -DgroupId=org.cqq -DartifactId=targetapp -Dpackage=org.cqq.targetapp -Dversion=0.0.1-SNAPSHOT

命令的参数可分为三部分:

  1. 功能参数:
    -DinteractiveMode=false:进入交互模式
    -DarchetypeCatalog=local:用来指定 maven-archetype-plugin 读取 archetype-catalog.xml 文件的位置(archetype-catalog.xml 的作用会在后面说到):

    • internal:maven-archetype-plugin 内置
    • local:本地,位置为~/.m2/archetype-catalog.xml
    • remote:Maven中央仓库
  2. 自定义可运行原型工程的坐标信息:
    -DarchetypeGroupId: 自定义 archetype 的 groupId
    -DarchetypeArtifactId: 自定义 archetype 的 artifactId
    -DarchetypeVersion: 自定义 archetype 的版本号

  3. 需要生成的目标项目的坐标信息:
    -DgroupId: 要生成的目标项目的 groupId
    -DartifactId: 要生成的目标项目的artifactId
    -Dpackage: 要生成的目标项目的包路径(正是用来填补上面提到的原型工程中被剔除的包路径,如果没有设置则默认值为 DgroupId + DartifactId)
    -Dversion: 要生成的目标项目的版本号

最终生成的目标项目结构如下:

D:\development\idea\workspace\mvn-archetype>cd targetappD:\development\idea\workspace\mvn-archetype\targetapp>tree /F
D:.
│  .gitignore
│  pom.xml
│
└─src├─main│  ├─java│  │  └─org│  │      └─cqq│  │          └─targetapp│  │                  MavenArchetypeTestApplication.java│  ││  └─resources│      │  application.yaml│      │  logback-spring-dev.xml│      ││      └─META-INF│              spring.factories│└─test└─java└─org└─cqq└─targetappMavenArchetypeTestApplicationTests.java

5. 小结

  1. 原型元工程中的代码可以理解为是最终生效模版文件的前身。生成模板文件后,可以二次进行修改,即原型元工程中的代码不是最终的模板内容,而是帮助我们生成原型工程。
  2. 原型元工程到原型工程的过渡,依赖元工程中的插件:maven-archetype-plugin
  3. 元工程中的插件 maven-archetype-plugin 使得原型工程中的最外层生成一个包含了原型打包(打包 archetype-resources 中的模板文件)依赖的 pom ,对生成的原型工程 install 即可生成最终的可执行的原型工程

archetype-catalog.xml

该文件用于说明去哪里寻找可运行原型工程来生成目标项目。前面我们使用的是 -DarchetypeCatalog=local 参数,也说明了参数值为 local 时会去寻找本地~/.m2/ 目录下寻找 archetype-catalog.xml 文件。下面看一下该文件的内容:

<?xml version="1.0" encoding="UTF-8"?><archetype-catalog><archetypes><archetype><groupId>priv.cqq</groupId><artifactId>maven-archetype-test-archetype</artifactId><version>0.0.1-SNAPSHOT</version><description>maven-archetype-test-archetype</description></archetype></archetypes>
</archetype-catalog>

里面描述的正是原型工程 mvn install 后坐标信息,也说明了是在 install 后在该文件中添加坐标信息的。

原型工程中的 META-INF 目录

该目录下包含两个文件:archetype.xmlarchetype-metadata.xml

1. archetype.xml

该文件中的内容很简单:资源文件清单。

<?xml version="1.0" encoding="UTF-8"?>
<archetype><id>maven-archetype-test</id><sources><source>src\main\java\priv\cqq\mavenarchetypetest\MavenArchetypeTestApplication.java</source></sources><testSources><source>src\test\java\priv\cqq\mavenarchetypetest\MavenArchetypeTestApplicationTests.java</source></testSources><resources><resource>src\main\resources\application.yaml</resource><resource>src\main\resources\logback-spring-dev.xml</resource><resource>src\main\resources\META-INF\spring.factories</resource><resource>.gitignore</resource></resources>
</archetype>

2. archetype-metadata.xml

官方文档。该文件是元数据文件,主要使用两类标签:

  1. <requiredProperties>:自定义参数,可在模板文件中通过 ${} 的形式进行值引用
  2. fileSets:配置模板文件扫描规则。filtered 设置为 true 时,才会解析模板文件中的值引用,替换为具体值。
<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor name="maven-archetype-test"><requiredProperties><requiredProperty key="customParam1"><defaultValue>customParam1</defaultValue></requiredProperty><requiredProperty key="customParam2"><defaultValue>customParam2</defaultValue></requiredProperty></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>**/*.xml</include><include>**/*.factories</include><include>**/*.yaml</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>
</archetype-descriptor>

思考一下,以上的自定义参数配置的意义是什么呢?用途在哪里?

当我们通过 idea 创建项目时,实际上,是可以选择 Archetype 的。idea 默认为我们提供了一些原型模板,当我们选中后,根据该模板会快速生成一个 maven 项目。

idea 创建项目

那么模板内容不能是死的对吧,可以根据用户的一些输入生成不同的内容。所以,当我们在编写自己的 Archetype 时,也应当如此。比如将一些配置:数据库连接配置、Redis 连接配置、Swagger 配置、MQ 配置、日志存储路径等等,都可以提取出配置项。这样,可使得最终生成的目标项目是能直接运行的,而不用找到各个配置类、文件,修改后才能运行。

值引用实践

清楚了 archetype-metadata.xml 的作用后,那么就来看下如何应用,以及有哪些需要注意的点。

  1. 执行命令生成原型项目:

    mvn clean archetype:create-from-project

  2. 在原型项目的 archetype-metadata.xml 中声明自定义属性:

    <requiredProperties><requiredProperty key="application-name"><defaultValue>WEB-APP</defaultValue></requiredProperty><requiredProperty key="log-home"><defaultValue>./applog</defaultValue></requiredProperty><requiredProperty key="enable-auto-configuration-classes"><defaultValue>com.xxx.xxx.SpringUtils</defaultValue></requiredProperty><requiredProperty key="component-scan-path"><defaultValue>com.xxx.xxx</defaultValue></requiredProperty>
    </requiredProperties>
    
  3. 检查 <fileSet> 标签中的 filtered 属性是否为 true & include 标签中的引入规则

    <?xml version="1.0" encoding="UTF-8"?>
    <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 encoding="UTF-8"> --><!--   <directory>src/main/resources</directory> --><!--   <includes> --><!--     <include>**/*.factories</include> --><!--     <include>**/*.yaml</include> --><!--   </includes> --><!-- </fileSet> --><!-- 补齐 filtered 属性 --><fileSet filtered="true" encoding="UTF-8"><directory>src/main/resources</directory><includes><include>**/*.factories</include><include>**/*.yaml</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>
    
  4. 模板文件中引用

    4.1 MavenArchetypeTestApplication (需修正)

    #set( $symbol_pound = '#' )
    #set( $symbol_dollar = '$' )
    #set( $symbol_escape = '\' )
    package ${package};import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.ComponentScan;@ComponentScan(value = "${symbol_dollar}{component-scan-path}")
    @SpringBootApplication
    public class MavenArchetypeTestApplication {public static void main(String[] args) {SpringApplication.run(MavenArchetypeTestApplication.class, args);}}// ====================== 修正值引用的取值方式 =======================@ComponentScan(value = "${component-scan-path}")
    @SpringBootApplication
    public class MavenArchetypeTestApplication {public static void main(String[] args) {SpringApplication.run(MavenArchetypeTestApplication.class, args);}
    }
    

    4.2 spring.factories(无需修正)

    # Auto Configure
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=${enable-auto-configuration-classes}
    

    4.3 application.yaml(无需修正)

    server:port: 8080servlet:context-path: /session:timeout: PT1Hspring:application:name: ${application-name}	
    

    4.4 logback-spring-dev.xml(需修正)

    #set( $symbol_pound = '#' )
    #set( $symbol_dollar = '$' )
    #set( $symbol_escape = '\' )
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration debug="false" scan="true" scanPeriod="1 seconds"><contextName>logback-spring</contextName><springProperty scope="context" name="springProfile" source="spring.profiles.active"/><!-- <property name="LOG_HOME" value="${symbol_dollar}{logHome}"/> --><!-- 修正值引用的取值方式 --><property name="LOG_HOME" value="${logHome}"/><property name="FILE_PATTERN"value="%yellow([${symbol_dollar}{springProfile:-}]) %magenta([%X{TraceId}]) %magenta(%d{yyyy-MM-dd HH:mm:ss.SSS}) %yellow(%-5level) %magenta(${symbol_dollar}{PID:-}) %-20(%yellow([%20.20thread])) %cyan([%-40logger{40}:%L]) -> %msg%n"/><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${symbol_dollar}{FILE_PATTERN}</pattern><charset>utf-8</charset></encoder></appender><root level="info"><appender-ref ref="STDOUT"/></root>
    </configuration>
    

    4.5 效果

    mvn install 原型工程后,生成目标项目:

    mvn archetype:generate -DinteractiveMode=false -DarchetypeGroupId=priv.cqq -DarchetypeArtifactId=maven-archetype-test-archetype -DarchetypeVersion=0.0.1-SNAPSHOT -DgroupId=org.cqq -DartifactId=targetapp -Dpackage=org.cqq.targetapp -Dversion=0.0.1-SNAPSHOT

    java值引用factories值引用
    yaml值引用
    xml值引用

值引用的转译问题

可以看到,前面分别对于 java、xml 文件中的值引用进行了修正,就是在解决 maven archetype plugin 使用的 Velocity 模板对特殊字符转的译问题。

1. 不修正

先说如果不修正的情况,以需要修正的 logback-spring-dev.xml 为例:
<property name="LOG_HOME" value="${symbol_dollar}{logHome}"/>,对于这段 xml,在最终生成的目标项目中的输出内容为 <property name="LOG_HOME" value="${logHome}"/>,即不会进行值替换,保留原有内容。

2. 修正后

删除{symbol_dollar}后,仅保留:${logHome},这样就可以正确的读取到自定义变量。

3. 原因分析

换个角度看,也不能定义为一个问题。因为 maven-archetype 并不知道模板文件中的这个值引用是在引用目标项目自身的配置文件中的属性值,还是要引用用于构建目标项目的自定义属性值。所以统一进行了转译,保留原本的内容。

4. 为什么只有 java、xml 模板文件中转译问题

为什么 spring.factories / application.yaml 没有这个问题呢?在回顾一下 archetype-metadata.xml 中我们是不是补齐了一个 fileSet 的 filtered 属性?原 fileSet 中过滤的正是 factories 与 yaml 类型文件,但是没有 filtered 属性。

<!-- <fileSet encoding="UTF-8"> -->
<!--   <directory>src/main/resources</directory> -->
<!--   <includes> -->
<!--     <include>**/*.factories</include> -->
<!--     <include>**/*.yaml</include> -->
<!--   </includes> -->
<!-- </fileSet> -->

所以,可以得出两个结论:

  1. 执行 mvn archetype:generate 默认只会对 java、xml 类型文件进行转译,并在元数据文件中的 fileSet 标签中设置 filtered 属性为 true
  2. 被转译的文件中的 #$\ 特殊符号会被转译
    #set( $symbol_pound = '#' )
    #set( $symbol_dollar = '$' )
    #set( $symbol_escape = '\' )
    

那么我们是否可以在生成原型工程时,不仅仅是对 java、xml 文件进行值引用的解析,也可以对更多类型的文件进行值引用解析呢?配置 mvn archetype:create-from-project 的参数,再次执行生成原型工程命令:

mvn clean archetype:create-from-project
-Darchetype.filteredExtentions=java,xml,yaml,factories
-DarchetypeCatalog=local

查看一下生成的 archetype-metadata.xml

<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor name="maven-archetype-test"><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><include>**/*.factories</include><include>**/*.yaml</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>
</archetype-descriptor>

archetype.properties

 archetype.properties

该文件用于设置 mvn archetype:create-from-project 的参数,不仅可以设置 filteredExtentions,还可以配置自定义属性,官方文档 。最终,会直接在元数据文件中生成参数相对应的配置。

# 内置参数
archetype.filteredExtensions=java,yml,yaml,xml,txt,groovy,cs,mdo,aj,jsp,gsp,vm,html,xhtml,properties,factories,.classpath,.project
# Velocity templates encoding (Default UTF-8)
archetype.encoding=UTF-8
# Archetype project output dic (Default path as below, cannot be modified)
# outputDirectory: ${project.build.directory}/generated-sources/archetype# 自定义参数
extParam1=extParamValue1
extParam2=extParamValue2

自定义参数会被生成到元数据文件中的 <requiredProperty> 标签,以便模板文件中可以通过${}进行取值。标签中的 key 即配置项的 key,<requiredProperty> 的子标签 <defaultValue> 的值即为配置项值。

filteredExtensions 属性,则会在 fileSet 标签的 filtered 属性上设置 true 值

指定配置文件执行:

mvn clean archetype:create-from-project
-Darchetype.properties=archetype.properties
-DarchetypeCatalog=local

<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor name="maven-archetype-test"><requiredProperties><requiredProperty key="extParam2"><defaultValue>extParamValue2</defaultValue></requiredProperty><requiredProperty key="extParam1"><defaultValue>extParamValue1</defaultValue></requiredProperty></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>**/*.xml</include><include>**/*.factories</include><include>**/*.yaml</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>
</archetype-descriptor>

自定义属性值的二次设置

执行生成目标项目命令时,我们可以再次指定自定义参数值,覆盖掉元数据文件中配置的自定义参数的默认值。测试流程如下:

1. 生成原型工程

mvn clean archetype:create-from-project
-Darchetype.properties=archetype.properties
-DarchetypeCatalog=local

2. 生成目标项目

修正测试文件中的转义:

#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
server:port: 8080servlet:context-path: /session:timeout: PT1Hspring:profiles:active: devapplication:# name: ${symbol_dollar}{extParam1} / ${symbol_dollar}{extParam2}name: ${extParam1} / ${extParam2}

3. 生成目标项目

mvn archetype:generate
-DinteractiveMode=false
-DarchetypeCatalog=local
-DarchetypeGroupId=priv.cqq
-DarchetypeArtifactId=maven-archetype-test-archetype
-DarchetypeVersion=0.0.1-SNAPSHOT
-DgroupId=org.cqq
-DartifactId=targetapp
-Dpackage=org.cqq.targetapp
-Dversion=0.0.1-SNAPSHOT
-DextParam1=extParamValue1-modified

目标项目文件内容如下:

最终测试文件输出

多模块

前面的案例都是在单模块项目中完成的。对于多模块,构建各个阶段工程的方式、最终的原型工程的使用,与单模块相比没有什么不同,因为构建命令:

mvn archetype:create-from-project

会帮助我们做好多模块的处理,将多模块的信息自动填写到元数据文件中,我们仅需构建好一个正确的多模块原型元工程即可。如下:

多模块原型元工程

生成原型工程后,元数据文件中生成的多模块信息描述:

<modules><module id="${rootArtifactId}-common" dir="__rootArtifactId__-common" name="${rootArtifactId}-common"><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>**/*.factories</include></includes></fileSet><fileSet encoding="UTF-8"><directory>src/main/resources</directory><includes><include>**/*.lua</include></includes></fileSet></fileSets></module><module id="${rootArtifactId}-service" dir="__rootArtifactId__-service" name="${rootArtifactId}-service"><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}-web" dir="__rootArtifactId__-web" name="${rootArtifactId}-web"><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><include>**/*.yaml</include></includes></fileSet></fileSets></module>
</modules>

原型工程的实际应用

1. 命令行

在前面已经说过了:

mvn archetype:generate -DinteractiveMode=false -DarchetypeCatalog=local
-DarchetypeGroupId=priv.cqq
-DarchetypeArtifactId=maven-archetype-test-archetype
-DarchetypeVersion=0.0.1-SNAPSHOT
-DgroupId=org.cqq -DartifactId=targetapp
-Dpackage=org.cqq.targetapp
-Dversion=0.0.1-SNAPSHOT
-DextParam1=extParamValue1-modified
-DextParam2=extParamValue2-modified

2. idea 导入

将原型成功 install 后,在 Archetype 项点击 add 按钮,输入已 install 的可运行原型工程的坐标信息:

idea使用archetype创建项目-1

添加后,在 Additional Properties 中就可以回显出所有的自定义参数,非常好用!

idea使用archetype创建项目-2
点击创建,生成的项目结构如下:

idea使用archetype创建项目-3

遇到的坑与经验总结

1. 自定义属性问题

1.1 多层级自定义属性无法被正确引用

多层级的自定属性是无法被解析后进行值替换的,比如:ext.server.port=8080

  1. 通过指定-Darchetype.properties文件的方式从原型元工程生成原型工程,多层级的自定义属性都不会生成 requiredProperty 标签在元数据文件中
  2. 即使手动在元数据文件中补充了多层级属性的 requiredProperty 标签,在通过可运行原型工程生成目标项目时,也无法通过 ${ext.server.port} 正确的引用到实际配置值
1.2 预先在元工程定义的值引用无法正确同步到原型工程

当我们在原型元工程中就定义好模板文件需要引用的单级自定义属性,并通过命令创建原型工程:

mvn clean archetype:create-from-project
-Darchetype.properties=archetype.properties

期望:

  1. 原型工程中的模板文件也同时定义好了自定义属性值引用
  2. 帮助我们生成 archetype-metadata.xml 文件

但,Velocity 解析的非常不智能!原型元工程中提前编写好的自定义属性值引用,经常无法正确的在原型工程中生成,常发生格式错乱。也就是说,最后还是需要校验一遍最终的模板文件后,在进行原型工程的 install

1.3 经验总结
  1. 若期望在原型元工程中就定义好自定义属性引用,并能更少发生解析错误的生成原型工程。经过多次尝试,单层级自定义属性名风格最好为大驼峰的风格,能够尽少的发生无法正确同步的问题
  2. 为什么一定要在原型元工程中就定义好自定义属性引用,这是因为后期可能会经常改动模板,以至于我们需要多次的重新构建出原型工程。如果不再原型元工程中提前编写好自定义属性引用,那么每次都需要整体改一遍新生成的原型工程
  3. 自定义属性最好加上特殊前缀:在原型工程中定义的自定属性引用:${attr},在通过命令生成原型工程时,会被解析为 ${symbol_dollar}{attr}。为了自定义原型属性可以生效,我们需要剔除 {symbol_dollar} 这部分,这个在前面说过了,否则不会正确完成值引用解析,会被原样输出到结果代码文件中。除此之外,项目中原本的 ${attr} 引用也会被转译,为了区分是原型自定义属性引用还是原生属性引用,我们可以通过设置前缀的方式,快速通过编辑器进行内容替换:保留转译后的原生属性引用的同时,将原型自定义属性引用改为 ${attr} 的格式。
  4. requiredProperty 标签是否需要默认值:个人更倾向不给默认值,在构建目标项目时手动传入。
  5. ${package} 的自动替换:在原型元工程中所有的 Java 文件间的引用,都会在生成原型工程时被转为 ${package}。如下例:priv.cqq.multimodulebackend 就会被转为 ${package}。进而使得生成目标项目时,元工程文件间的引用都可以正确的被替换为目标项目文件间的引用。
    @Pointcut("execution(*priv.cqq.multimodulebackend.web.controller..*Controller.*(..))")
    private void log() {
    }
    
    总结下来即:在编写原型元工程时无需考虑包路径问题,最终都可以被正确的转为目标项目的包路径。

2. 升级到新版本 maven-archetype 插件遇到的问题

由 2.0-alpha-4 远古版本升级到 2021 年最新发布的 3.2.1 版本:

<plugin><!-- <groupId>org.apache.maven.plugins</groupId> --><!-- <artifactId>maven-archetype-plugin</artifactId> --><!-- <version>2.0-alpha-4</version> --><groupId>org.apache.maven.plugins</groupId><artifactId>maven-archetype-plugin</artifactId><version>3.2.1</version>
</plugin>
2.1 .m2/settings.xml 文件不存在

执行生成原型工程命令失败:

mvn clean archetype:create-from-project
-Darchetype.properties=archetype.properties
-DarchetypeCatalog=local

[WARN] Maven will be executed in interactive mode, but no input stream has been configured for this MavenInvoker instance.
[ERROR] Error executing Maven.
[ERROR] The specified user settings file does not exist: /Users/congqingquan/.m2/settings.xml
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for multi-module-backend 1.0-SNAPSHOT:
[INFO] 
[INFO] multi-module-backend ............................... FAILURE [  3.155 s]
[INFO] multi-module-backend-common ........................ SUCCESS [  0.003 s]
[INFO] multi-module-backend-domain ........................ SUCCESS [  0.003 s]
[INFO] multi-module-backend-dao ........................... SUCCESS [  0.003 s]
[INFO] multi-module-backend-manager ....................... SUCCESS [  0.003 s]
[INFO] multi-module-backend-integration ................... SUCCESS [  0.005 s]
[INFO] multi-module-backend-service ....................... SUCCESS [  0.003 s]
[INFO] multi-module-backend-web ........................... SUCCESS [  0.004 s]
[INFO] multi-module-backend-mq ............................ SUCCESS [  0.004 s]
[INFO] multi-module-backend-start ......................... SUCCESS [  0.004 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.746 s
[INFO] Finished at: 2024-03-03T02:08:04+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-archetype-plugin:3.2.1:create-from-project (default-cli) on project multi-module-backend: Invoker process ended with result different than 0! -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

提示 The specified user settings file does not exist: /Users/congqingquan/.m2/settings.xml

很明显这是在寻找默认的 maven settings 文件。由于我们使用的是自己的 maven,那么指定一下个人 maven settings 配置文件的位置就好了。追加 -s 参数:

mvn clean archetype:create-from-project
-Darchetype.properties=archetype.properties
-DarchetypeCatalog=local
-s /Users/congqingquan/development/maven/apache-maven-3.6.3/conf/settings.xml

3. 多模块原型元工程的包路径替换问题

前面提到:原型元工程中的包层级会被剔除,切换到了根路径。后面根据可运行的原型工程生成目标项目时,可动态切换为用户输入的设置路径。在多模块元工程中,这个是有限制的,只能剔除两级。很坑!

元工程中的结构:

多模块原型元工程的包路径替换问题-1

生成的原型工程结构(pck 并没有被剔除):

多模块原型元工程的包路径替换问题-2

所以为了目标工程的包路径可以完全根据输入而定,元工程中的代码结构,最多保留两级。

这篇关于Maven archetype 原型插件详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/812211

相关文章

Java中注解与元数据示例详解

《Java中注解与元数据示例详解》Java注解和元数据是编程中重要的概念,用于描述程序元素的属性和用途,:本文主要介绍Java中注解与元数据的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参... 目录一、引言二、元数据的概念2.1 定义2.2 作用三、Java 注解的基础3.1 注解的定义3.2 内

JavaScript中的isTrusted属性及其应用场景详解

《JavaScript中的isTrusted属性及其应用场景详解》在现代Web开发中,JavaScript是构建交互式应用的核心语言,随着前端技术的不断发展,开发者需要处理越来越多的复杂场景,例如事件... 目录引言一、问题背景二、isTrusted 属性的来源与作用1. isTrusted 的定义2. 为

使用Python实现操作mongodb详解

《使用Python实现操作mongodb详解》这篇文章主要为大家详细介绍了使用Python实现操作mongodb的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、示例二、常用指令三、遇到的问题一、示例from pymongo import MongoClientf

一文详解Python中数据清洗与处理的常用方法

《一文详解Python中数据清洗与处理的常用方法》在数据处理与分析过程中,缺失值、重复值、异常值等问题是常见的挑战,本文总结了多种数据清洗与处理方法,文中的示例代码简洁易懂,有需要的小伙伴可以参考下... 目录缺失值处理重复值处理异常值处理数据类型转换文本清洗数据分组统计数据分箱数据标准化在数据处理与分析过

SpringBoot项目中Maven剔除无用Jar引用的最佳实践

《SpringBoot项目中Maven剔除无用Jar引用的最佳实践》在SpringBoot项目开发中,Maven是最常用的构建工具之一,通过Maven,我们可以轻松地管理项目所需的依赖,而,... 目录1、引言2、Maven 依赖管理的基础概念2.1 什么是 Maven 依赖2.2 Maven 的依赖传递机

详解如何在React中执行条件渲染

《详解如何在React中执行条件渲染》在现代Web开发中,React作为一种流行的JavaScript库,为开发者提供了一种高效构建用户界面的方式,条件渲染是React中的一个关键概念,本文将深入探讨... 目录引言什么是条件渲染?基础示例使用逻辑与运算符(&&)使用条件语句列表中的条件渲染总结引言在现代

详解Vue如何使用xlsx库导出Excel文件

《详解Vue如何使用xlsx库导出Excel文件》第三方库xlsx提供了强大的功能来处理Excel文件,它可以简化导出Excel文件这个过程,本文将为大家详细介绍一下它的具体使用,需要的小伙伴可以了解... 目录1. 安装依赖2. 创建vue组件3. 解释代码在Vue.js项目中导出Excel文件,使用第三

SQL注入漏洞扫描之sqlmap详解

《SQL注入漏洞扫描之sqlmap详解》SQLMap是一款自动执行SQL注入的审计工具,支持多种SQL注入技术,包括布尔型盲注、时间型盲注、报错型注入、联合查询注入和堆叠查询注入... 目录what支持类型how---less-1为例1.检测网站是否存在sql注入漏洞的注入点2.列举可用数据库3.列举数据库

Linux之软件包管理器yum详解

《Linux之软件包管理器yum详解》文章介绍了现代类Unix操作系统中软件包管理和包存储库的工作原理,以及如何使用包管理器如yum来安装、更新和卸载软件,文章还介绍了如何配置yum源,更新系统软件包... 目录软件包yumyum语法yum常用命令yum源配置文件介绍更新yum源查看已经安装软件的方法总结软

java图像识别工具类(ImageRecognitionUtils)使用实例详解

《java图像识别工具类(ImageRecognitionUtils)使用实例详解》:本文主要介绍如何在Java中使用OpenCV进行图像识别,包括图像加载、预处理、分类、人脸检测和特征提取等步骤... 目录前言1. 图像识别的背景与作用2. 设计目标3. 项目依赖4. 设计与实现 ImageRecogni