01 引言
博主在上一篇博客《深度剖析Dinky源码》主要分析了dinky
的项目结构,以及源码执行流程。
同时,博主发现该项目的maven
打包也是有值得学习的地方,我们看看其结构:
本文来讲解下Dinky是如何使用maven的特性来打包的。
02 根节点
这里是精简了根节点的pom文件内容之后,添加注释的内容:
<?xml version="1.0" encoding="UTF-8"?> <!-- Maven项目的POM文件 --> <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"> <!-- Maven项目的模型版本 --> <modelVersion>4.0.0</modelVersion> <!-- 项目的唯一标识符 --> <groupId>org.dinky</groupId> <artifactId>dinky</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>pom</packaging> <!-- 项目的名称 --> <name>Dinky :</name> <!-- 包含的子模块列表 --> <modules> <module>dinky-admin</module> <module>dinky-assembly</module> <!-- 其他依赖,这里不再详述。。。。 --> </modules> <!-- 属性列表 --> <properties> <!-- 运行时范围为provided(用于生产环境)或compile(用于开发环境) --> <scope.runtime>provided</scope.runtime> <snakeyaml.version>1.33</snakeyaml.version> <!-- 其它属性,这里不再详述。。。 --> </properties> <!-- 依赖管理 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>${assertj.version}</version> </dependency> <!-- 其它依赖,这里不再详述。。。 --> </dependencies> </dependencyManagement> <!-- 构建配置 --> <build> <!-- 插件管理 --> <pluginManagement> <plugins> <!-- 清理插件,用于清理目标目录 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-clean-plugin</artifactId> <version>${maven-clean-plugin.version}</version> </plugin> <!-- 编译插件,用于编译源代码 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven-compiler-plugin.version}</version> <configuration> <!-- 源码和目标字节码版本 --> <source>${target.java.version}</source> <target>${target.java.version}</target> <testSource>${target.java.version}</testSource> <testTarget>${target.java.version}</testTarget> </configuration> </plugin> <!-- 其它插件 --> </plugins> </pluginManagement> <!-- 插件列表 --> <plugins> <!-- 帮助插件,用于显示Maven帮助信息 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-help-plugin</artifactId> </plugin> <!-- 依赖插件,用于管理项目依赖 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> </plugin> <!-- 其它插件 --> </plugins> </build> <!-- 项目的URL --> <url>http://www.dlink.top</url> <!-- 项目的初始年份 --> <inceptionYear>2014</inceptionYear> <!-- 项目的许可证信息 --> <licenses> <license> <name>The Apache Software License, Version 2.0</name> <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url> <distribution>repo</distribution> </license> </licenses> <!-- 项目的源代码管理信息 --> <scm> <connection>git@github.com:DataLinkDC/dinky.git</connection> <url>https://github.com/DataLinkDC/dinky</url> </scm> <!-- 项目的仓库配置 --> <repositories> <repository> <id>apache-snapshots</id> <url>https://maven.aliyun.com/repository/apache-snapshots</url> </repository> </repositories> <!-- 配置不同的Maven配置文件 --> <profiles> <!-- 阿里云仓库配置 --> <profile> <id>aliyun</id> <activation> <activeByDefault>true</activeByDefault> </activation> <repositories> <repository> <id>aliyun</id> <url>https://maven.aliyun.com/repository/central</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>aliyun</id> <url>https://maven.aliyun.com/repository/central</url> </pluginRepository> </pluginRepositories> </profile> <!-- Web配置 --> <profile> <id>web</id> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> <!-- 开发环境配置 --> <profile> <id>dev</id> <properties> <!-- 运行时范围为compile(用于开发环境) --> <scope.runtime>compile</scope.runtime> </properties> </profile> <!-- 生产环境配置 --> <profile> <id>prod</id> <activation> <activeByDefault>true</activeByDefault> <property> <name>!dev</name> </property> </activation> <properties> <!-- 运行时范围为provided(用于生产环境) --> <scope.runtime>provided</scope.runtime> </properties> </profile> <!-- Flink 1.14配置 --> <profile> <id>flink-1.14</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <dinky.flink.version>1.14</dinky.flink.version> </properties> </profile> <!-- Flink 1.15配置 --> <profile> <id>flink-1.15</id> <properties> <dinky.flink.version>1.15</dinky.flink.version> </properties> </profile> <!-- 其它配置 --> </profiles> </project>
从内容里面,相较于普通的项目,个人认为比较值得去学习的是里面的插件管理(Plugins
)、打包多版本管理(Profiles
)、以及 assembly
打包管理 ,下面来讲下。
03 maven插件管理
从根目录下的pom文件节点,可以看到在build
节点下,定义了pluginManagement
(插件管理节点)和plugins
(插件列表节点)。
大致有如下内容,它们的作用是:
插件类型 | artifactId | 作用 |
清理插件 | maven-clean-plugin | 清理项目构建产生的文件和目录 |
编译插件 | maven-compiler-plugin | 编译Java源代码 |
单元测试插件 | maven-surefire-plugin | 运行单元测试 |
帮助插件 | maven-help-plugin | 提供Maven帮助文档 |
依赖管理插件 | maven-dependency-plugin | 管理项目的依赖 |
强制执行插件 | maven-enforcer-plugin | 强制执行项目构建规则 |
JAR插件 | maven-jar-plugin | 创建可执行的JAR文件 |
代码格式化插件 | spotless-maven-plugin | 格式化代码和POM文件,以及进行其他代码检查和修复操作 |
构建助手插件 | build-helper-maven-plugin | 帮助处理构建过程中的辅助任务 |
Shade插件 | maven-shade-plugin | 创建可执行的Uber JAR,将所有依赖打包到一个JAR文件中 |
Japicmp插件 | japicmp-maven-plugin | 比较两个Java类或JAR文件之间的差异 |
Javadoc插件 | maven-javadoc-plugin | 生成Java文档 |
值得注意的是,该项目还可以打包web
项目,直接切换到dinky-web/pom.xml
,里面pom
的内容如下:
<?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>org.dinky</groupId> <artifactId>dinky</artifactId> <!-- 指定父项目的版本 --> <version>1.0.0-SNAPSHOT</version> </parent> <!-- 当前子项目的artifactId --> <artifactId>dinky-web</artifactId> <packaging>pom</packaging> <!-- 项目名称 --> <name>Dinky : Dinky-Web</name> <build> <!-- 构建产物的最终名称,使用当前项目的artifactId和version --> <finalName>${project.artifactId}-${project.version}</finalName> <plugins> <!-- 调用npm命令插件 --> <plugin> <!-- 插件的groupId --> <groupId>com.github.eirslett</groupId> <!-- 插件的artifactId --> <artifactId>frontend-maven-plugin</artifactId> <!-- 插件的版本号 --> <version>1.12.0</version> <configuration> <!-- 指定所需的Node.js版本 --> <nodeVersion>v14.17.0</nodeVersion> <!-- 指定所需的npm版本 --> <npmVersion>7.19.0</npmVersion> <!-- 国内node下载加速 --> <!--<nodeDownloadRoot>https://mirrors.huaweicloud.com/nodejs/</nodeDownloadRoot>--> <!--<npmDownloadRoot>https://repo.huaweicloud.com/npm-software/</npmDownloadRoot>--> </configuration> <executions> <execution> <!-- 执行命令的唯一标识符 --> <id>install node and npm</id> <goals> <!-- 要执行的目标(goal) --> <goal>install-node-and-npm</goal> </goals> </execution> <execution> <!-- 执行命令的唯一标识符 --> <id>npm install</id> <goals> <!-- 要执行的目标(goal) --> <goal>npm</goal> </goals> <configuration> <!-- 国内npm源加速可在后面加入(去掉空格) - -registry https://repo.huaweicloud.com/repository/npm/ --> <arguments>install --force</arguments> <!-- npm命令及其参数 --> </configuration> </execution> <execution> <!-- 执行命令的唯一标识符 --> <id>npm run build</id> <goals> <!-- 要执行的目标(goal) --> <goal>npm</goal> </goals> <configuration> <!-- npm命令及其参数 --> <arguments>run build</arguments> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
其实原理就是使用了前端的打包插件(frontend-maven-plugin
),执行与npm相关的操作
04 profiles(多版本管理)
Profiles
提供了一种灵活和可配置的方式,能够根据不同的需求和环境来定制和管理项目的构建过程和行为,这使得开发者可以更好地适应不同的开发、测试和部署场景。
从上图可以得知,通过选择右侧的能指定特定的profile,同时也可以使用maven命令来构建(使用-P的形式,逗号分隔多环境),例如:
# 如若修改版本,按以下指定即可。flink可支持多版本(1.11-1.16) mvn clean install -Dmaven.test.skip=true -P pord,scala-2.11,flink-1.14
这是,dinky官网提示不同profile的作用:
05 assembly打包(归档管理)
在根目录的pom
节点,modules
下,含有dinky-assembly
模块,它允许将多个文件和依赖项聚合成一个可执行的分发包或归档文件,方便部署和发布项目。
进入dinky-assembly目录,看看器其pom文件里面的内容(已含注释):
<?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>org.dinky</groupId> <artifactId>dinky</artifactId> <version>1.0.0-SNAPSHOT</version> </parent> <!-- 项目的唯一标识符 --> <artifactId>dinky-assembly</artifactId> <!-- 打包类型为 POM,不生成实际的构建产物 --> <packaging>pom</packaging> <!-- 项目名称 --> <name>Dinky : Assembly</name> <!-- 构建配置 --> <build> <!-- 构建插件 --> <plugins> <!-- Maven Assembly 插件 --> <plugin> <!-- 插件的groupId --> <groupId>org.apache.maven.plugins</groupId> <!-- 插件的artifactId --> <artifactId>maven-assembly-plugin</artifactId> <!-- 插件的执行配置 --> <executions> <!-- 执行配置 --> <execution> <!-- 执行的目标阶段 --> <phase>package</phase> <!-- 执行的目标 --> <goals> <goal>single</goal> </goals> <!-- 插件的配置 --> <configuration> <!-- 最终生成的分发包的名称 --> <finalName>${project.parent.artifactId}-release-${project.version}</finalName> <!-- 是否追加 Assembly 的标识符到最终生成的分发包名称中 --> <appendAssemblyId>false</appendAssemblyId> <!-- 指定 Assembly 描述符的位置 --> <descriptors> <descriptor>src/main/assembly/package.xml</descriptor> </descriptors> <!-- 最终生成的分发包的输出目录 --> <outputDirectory>${project.parent.basedir}/build/</outputDirectory> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
再进入Assembly 描述文件(src/main/assembly/package.xml
),看看里面的内容:
<assembly> <!-- 分发包的唯一标识符,使用项目的版本号 --> <id>${project.version}</id> <!-- 分发包的格式 --> <formats> <format>tar.gz</format> </formats> <!-- 是否包含基础目录 --> <includeBaseDirectory>true</includeBaseDirectory> <!-- 文件集合配置 --> <fileSets> <!-- 定义一个文件集合 --> <fileSet> <!-- 文件所在目录 --> <directory>${project.parent.basedir}/script/bin</directory> <!-- 文件输出目录 --> <outputDirectory>./</outputDirectory> <!-- 文件行结束符类型 --> <lineEnding>unix</lineEnding> <!-- 文件权限模式 --> <fileMode>0755</fileMode> <!-- 包含的文件 --> <includes> <include>auto.sh</include> </includes> </fileSet> <!-- 定义另一个文件集合 --> <fileSet> <!-- 文件所在目录 --> <directory>${project.parent.basedir}/dinky-admin/target/classes</directory> <!-- 文件输出目录 --> <outputDirectory>config</outputDirectory> <!-- 包含的文件 --> <includes> <include>**/*.yml</include> <include>**/*.yaml</include> <include>**/log4j2.xml</include> <include>**/DinkyFlinkDockerfile</include> </includes> </fileSet> <!-- 更多文件集合的定义,下面列举部分示例 --> <!-- 定义一个文件集合 --> <fileSet> <!-- 文件所在目录 --> <directory>${project.parent.basedir}/build/extends/</directory> <!-- 文件输出目录 --> <outputDirectory>plugins/flink1.13</outputDirectory> <!-- 包含的文件 --> <includes> <include>dinky-catalog-mysql-1.13-${project.version}.jar</include> <include>dinky-client-1.13-${project.version}.jar</include> <include>dinky-connector-jdbc-1.13-${project.version}.jar</include> </includes> </fileSet> <!-- 定义一个文件集合 --> <fileSet> <!-- 文件所在目录 --> <directory>${project.parent.basedir}/build/extends/</directory> <!-- 文件输出目录 --> <outputDirectory>plugins/flink1.14</outputDirectory> <!-- 包含的文件 --> <includes> <include>dinky-catalog-mysql-1.14-${project.version}.jar</include> <include>dinky-client-1.14-${project.version}.jar</include> <include>dinky-connector-jdbc-1.14-${project.version}.jar</include> </includes> </fileSet> <!-- 更多文件集合的定义,下面列举部分示例 --> <!-- 定义一个文件集合 --> <fileSet> <!-- 文件所在目录 --> <directory>${project.parent.basedir}/build/extends/</directory> <!-- 文件输出目录 --> <outputDirectory>plugins</outputDirectory> <!-- 包含的文件 --> <includes> <include>dinky-client-base-${project.version}.jar</include> </includes> </fileSet> <!-- 更多文件集合的定义,下面列举部分示例 --> <!-- 定义一个文件集合 --> <fileSet> <!-- 文件所在目录 --> <directory>${project.parent.basedir}/dinky-metadata/dinky-metadata-clickhouse/target</directory> <!-- 文件输出目录 --> <outputDirectory>lib</outputDirectory> <!-- 包含的文件 --> <includes> <include>dinky-metadata-clickhouse-${project.version}.jar</include> </includes> </fileSet> <!-- 更多文件集合的定义,下面列举部分示例 --> <!-- 定义一个文件集合 --> <fileSet> <!-- 文件所在目录 --> <directory>${project.parent.basedir}/docker/app</directory> <!-- 文件输出目录 --> <outputDirectory>jar</outputDirectory> <!-- 包含的文件 --> <includes> <include>Dockerfile</include> </includes> </fileSet> <!-- 更多文件集合的定义 --> </fileSets> </assembly>
以上是 <assembly>
元素的配置,它定义了如何将不同的文件集合打包到分发包中。每个 <fileSet>
元素指定了一个文件集合,包括要打包的文件所在的目录、输出目录和包含的文件。
通过配置多个 <fileSet>
元素,可以将不同的文件组织结构打包到分发包中。
06 文末
如果想更进一步去学习maven的高级特性,可以直接搜索maven的官网,里面有更丰富的教程:https://maven.apache.org/
希望能帮助到大家,谢谢大家的阅读,本文完!