Dinky 打包分析(进一步了解maven)

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
简介: Dinky 打包分析(进一步了解maven)

01 引言

Dinky源码:https://github.com/DataLinkDC/dinky

博主在上一篇博客《深度剖析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/

希望能帮助到大家,谢谢大家的阅读,本文完!

相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
Linux入门到精通
本套课程是从入门开始的Linux学习课程,适合初学者阅读。由浅入深案例丰富,通俗易懂。主要涉及基础的系统操作以及工作中常用的各种服务软件的应用、部署和优化。即使是零基础的学员,只要能够坚持把所有章节都学完,也一定会受益匪浅。
目录
相关文章
|
18天前
|
Java 应用服务中间件 Maven
Maven的三种项目打包方式——pom,jar,war的区别
Maven 提供了多种打包方式,分别适用于不同类型的项目。pom 用于父项目或聚合项目,便于项目的结构和依赖管理;jar 用于Java类库或可执行的Java应用程序;war 则专用于Java Web应用程序的部署。理解这些打包方式的用途和特点,可以帮助开发者更好地配置和管理Maven项目,确保构建和部署过程的顺利进行。无论是单模块项目还是多模块项目,选择合适的打包方式对于项目的成功至关重要。
53 3
|
1月前
|
Java Maven Android开发
【Azure Developer】VS Code打包Java maven Project 遇见 BUILD FAILURE
Unknown lifecycle phase "lean". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>
|
2月前
|
缓存 IDE Java
idea的maven项目打包时没有source下的文件
【10月更文挑战第21天】idea的maven项目打包时没有source下的文件
45 1
|
2月前
|
Java 测试技术 Maven
maven 打包命令
maven 打包命令
27 6
|
2月前
|
Java Linux Maven
IDEA如何用maven打包(界面和命令两种方式)
【10月更文挑战第14天】本文介绍了两种Maven项目打包方法:命令行与IDEA界面。首先确保已安装Maven并配置环境变量,通过`mvn -v`检查安装。命令行打包需进入项目目录,执行`mvn package`,之后在`target`目录查看结果。IDEA打包则需配置Maven路径,打开Maven Projects窗口,双击Lifecycle下的`package`阶段,同样在`target`目录查找生成文件,并在Build窗口查看日志以排查问题。
864 1
|
2月前
|
Java Shell Maven
Flink-11 Flink Java 3分钟上手 打包Flink 提交任务至服务器执行 JobSubmit Maven打包Ja配置 maven-shade-plugin
Flink-11 Flink Java 3分钟上手 打包Flink 提交任务至服务器执行 JobSubmit Maven打包Ja配置 maven-shade-plugin
119 4
|
2月前
|
Java 应用服务中间件 Maven
SpringBoot Maven 项目打包的艺术--主清单属性缺失与NoClassDefFoundError的优雅解决方案
SpringBoot Maven 项目打包的艺术--主清单属性缺失与NoClassDefFoundError的优雅解决方案
336 0
|
4月前
|
Java Maven
解决idea每次新建maven项目都需要重新配置maven的问题
解决idea每次新建maven项目都需要重新配置maven的问题
174 1
|
21天前
|
Java Maven
maven项目的pom.xml文件常用标签使用介绍
第四届人文,智慧教育与服务管理国际学术会议(HWESM 2025) 2025 4th International Conference on Humanities, Wisdom Education and Service Management
74 8
|
2月前
|
Java 关系型数据库 MySQL
Maven——创建 Spring Boot项目
Maven 是一个项目管理工具,通过配置 `pom.xml` 文件自动获取所需的 jar 包,简化了项目的构建和管理过程。其核心功能包括项目构建和依赖管理,支持创建、编译、测试、打包和发布项目。Maven 仓库分为本地仓库和远程仓库,远程仓库包括中央仓库、私服和其他公共库。此外,文档还介绍了如何创建第一个 SpringBoot 项目并实现简单的 HTTP 请求响应。
132 1
Maven——创建 Spring Boot项目

推荐镜像

更多