maven pom 配置 学习笔记(六)之 maven-dependency-plugin (依赖zip包并将其解压到某个目录下)
一、背景
一般情况下会认为 maven 是给Java工程使用的,但实际并不是,一个程序由多方构成,包括:自己编写的程序代码、依赖的第三方程序(可能是jar、可能就是一个二进制文件、或这个C++库等),基于此,自己编写的程序可以直接通过 maven依赖将自己需要的第三方程序自动加载到本地。
二、场景
1、 程序依赖的第三方程序在一个zip包中,目前需要将该 zip 通过 maven 依赖进来,程序打包生成成果物的时候,需要将zip包解压放到指定的目录中,供自己的程序执行时可调用。
这里仅是举简单的例子:
(1) 依赖的第三方zip包生成
工程目录结构:
这里通过pom.xml 及 assembly-zip-deploy.xml 将 consul 二进制文件打包 到一个 zip包中,可以看下这两个文件的配置内容。
pom.xml
<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> <groupId>com.summer</groupId> <artifactId>maven-assembly-demo</artifactId> <packaging>pom</packaging> <version>0.0.1-SNAPSHOT</version> <name>maven-assembly-demo</name> <description>demo for maven-assembly-plugin</description> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <id>assembly-package</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> <configuration> <descriptors> <descriptor>assembly-zip-deploy.xml</descriptor> </descriptors> <outputDirectory>output</outputDirectory> </configuration> </plugin> </plugins> </build> <!-- 内部开发版本发布库,这个必须配置,若不配置中央仓库的话,发布不了 --> <distributionManagement> <repository> <id>maven-releases</id> <name>maven-releases</name> <url>http://127.0.0.1:8081/repository/maven-releases/</url> </repository> <snapshotRepository> <id>maven-snapshots</id> <name>maven-snapshots</name> <url>http://127.0.0.1:8081/repository/maven-snapshots/</url> </snapshotRepository> </distributionManagement> </project>
assembly-zip-deploy.xml
<?xml version='1.0' encoding='UTF-8'?> <assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd"> <id>package</id> <formats> <format>zip</format> </formats> <!-- 该值为false表示 output下面不会有个根目录,名为 artifactId_version 是直接将 fileSets 中的 文件直接放在output下面,见 maven-assembly-demo-0.0.1-SNAPSHOT-package.zip zip包结构 值为true时,可见 maven-assembly-demo-0.0.1-SNAPSHOT-package-includebasedirectory.zip --> <includeBaseDirectory>false</includeBaseDirectory> <fileSets> <fileSet> <directory>zipDeploy</directory> <outputDirectory>/</outputDirectory> //将zipDeploy 目录下的文件复制到 maven-assembly-plugin 配置的 output 目录下 </fileSet> </fileSets> </assembly>
通过以上两个文件打出来的zip目录结构如下:
注意:
(a) zip包名字构成为:maven-assembly-plugin 配置的 finalName + assembly-zip-deploy.xml 配置的 id ,若 maven-assembly-plugin 中没有配置 finalName,则默认 finalName 为 artifactId-version,若想生成的 zip 不包含 assembly-zip-deploy.xml 配置的 id,可以在 maven-assembly-plugin 下配置 <appendAssemblyId>false</appendAssemblyId>。
(b) finalName + assembly-zip-deploy.xml 配置的 id 被包含在 zip 名字中之后,该 id 可以作为 classifier 来使用。
(2) 自己编写的程序工程依赖 (1) 中通过 maven-assembly-plugin 打出来的 zip 包。
工程目录结构:
该工程也使用了 maven-assembly-plugin 来进行打包,我们的目标是打包出来的成果物,bin 目录下要包含 (1) 中zip包中的 consul 二进制文件。
pom.xml
<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> <groupId>com.summer</groupId> <artifactId>maven-dependency-plugin-demo</artifactId> <packaging>pom</packaging> <version>0.0.1-SNAPSHOT</version> <name>maven-dependency-plugin-demo</name> <description>demo for maven-dependency-plugin</description> <dependencies> <dependency> <groupId>com.summer</groupId> <artifactId>maven-assembly-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <classifier>package</classifier> <type>zip</type> //依赖 zip 包 </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.8</version> <executions> <execution> <id>unpack</id> <phase>package</phase> <goals> <goal>unpack</goal> </goals> <configuration> //打包阶段将依赖的zip解压到指定的 bin 目录下 <artifactItems> <artifactItem> <groupId>com.summer</groupId> <artifactId>maven-assembly-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <classifier>package</classifier> <type>zip</type> <outputDirectory>${project.basedir}/bin</outputDirectory> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <id>assembly-package</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> <configuration> <descriptors> <descriptor>assembly-unpack-zip-deploy.xml</descriptor> </descriptors> <outputDirectory>output</outputDirectory> </configuration> </plugin> </plugins> </build> <!-- 内部开发版本发布库,这个必须配置,若不配置中央仓库的话,发布不了 --> <distributionManagement> <repository> <id>maven-releases</id> <name>maven-releases</name> <url>http://127.0.0.1:8081/repository/maven-releases/</url> </repository> <snapshotRepository> <id>maven-snapshots</id> <name>maven-snapshots</name> <url>http://127.0.0.1:8081/repository/maven-snapshots/</url> </snapshotRepository> </distributionManagement> </project>
assembly-unpack-zip-deploy.xml
<?xml version='1.0' encoding='UTF-8'?> <assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd"> <id>package</id> <formats> <format>zip</format> </formats> <includeBaseDirectory>false</includeBaseDirectory> <fileSets> <fileSet> <directory>${project.basedir}</directory> <outputDirectory>/</outputDirectory> <includes> <include>bin/**</include> <include>config/**</include> </includes> </fileSet> </fileSets> </assembly>
以上打出来的zip包结构为:
三、知识点说明
官网叙述地址:http://maven.apache.org/ref/3.6.3/maven-model/maven.html#class_dependency
1、精确匹配依赖某个构件(可以是从一个pom生成的多个成果物,如:log4j-to-slf4j-2.11.2.jar、log4j-to-slf4j-2.11.2-javadoc.jar、log4j-to-slf4j-2.11.2-sources.jar)
<dependency> 表示依赖一个构件,通过 <dependency> 的多个子属性精确匹配到某个构件,一个构件组成结构为:artifactid-version-classifier.type,如:上述例子 一下的(1) 生成的成果物为:maven-assembly-demo-0.0.1-SNAPSHOT-package.zip ,此时 artifactid为 assembly-demo,version 为 0.0.1-SNAPSHOT,classifier 为 package,type 为 zip,一般从同一个pom若出多个成果物的话,就是使用 classifier 进行区分的。
一般情况下,我们依赖都是这么些:
<dependency> <groupId>com.summer</groupId> <artifactId>maven-assembly-demo</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
默认:classifier为null,type 为 jar,上述表示依赖 maven-assembly-demo-0.0.1-SNAPSHOT.jar 包。官网提供了支持的type类型的范围,但是经过上面的例子感觉 type 不在该范围也是可以的,比如:zip
官网对这几个属性的解释为:
2、直接依赖的 jar包可以选择性的传递给依赖当前程序的程序
如: A 直接依赖 B(A pom 使用 dependency 标签直接依赖 B),现在 C 直接依赖 A,若A已经决定 B是否要被C间接依赖 ,可以使用 optional
A.pom
<dependency> <groupId>xxx</groupId> <artifactId>B</artifactId> <version>0.0.1-SNAPSHOT</version> <optional>true</optional> //表示 依赖A的程序必须自己声明依赖B,否则B的包不会被程序间接依赖到 </dependency>
C.pom
<dependency> <groupId>xxx</groupId> <artifactId>A</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
此时C的依赖列表里面不会有 B
<dependency> <groupId>xxx</groupId> <artifactId>A</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>xxx</groupId> <artifactId>B</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
此时C的依赖列表里面既有A也有B。
PS:
对于这种用法还需谨慎,一般A程序依赖B说明A的功能是需要B程序的,C使用A的功能很有可能也要B。这种用法一般在 Spring 里面看到过,它会使用 @ConditionOnClass(xxx.class)来决定注解该注解的类是否需要执行。