目录
前言
实现
多模块实现
maven-assembly-plugin插件实现
关于properties标签题外话(maven的内置变量)
前言
有时候我们需要在一个java工程内执行打包命令能生成多个jar包,每个jar包的具体内容都与具体实现类相绑定,这样的好处就是方便。比如我们项目中对外提供了插件扩展,第三方使用者只需要实现我们的插件接口,然后打成jar包上传到我们的项目中便可动态解析,而使用者的需求便是能在一个工程内同时编辑多个业务插件,最终打包时也能生成多个不同的jar包以作不同的用途,因此作为产品方需要给出一个demo供他们直接上手。
实现
多模块实现
这个应该很好理解,可以使用多模块的方式实现,每个模块就相当于一个插件,最终打包时直接mvn package便能在不同模块的target目录下输出各自的jar包,实现简单,但是层次上存在一个父子关系,而实际上并不存在,因此不太好。
maven-assembly-plugin插件实现
使用该插件配合描述文件实现,整体项目结构如下图:
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>
<groupId>qingcha.test</groupId>
<artifactId>multiPluginDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- 引入插件目标接口以及相关依赖 -->
<dependency>
<artifactId>hornet-web-api</artifactId>
<groupId>uyun.hornet</groupId>
<version>2.0.0-SNAPSHOT</version>
<!-- 表示已提供依赖范围,由于是作为插件jar包运行在主项目中,而主项目中存在该依赖,因此实际运行的时候并不需要maven重复引入一遍,
因此该依赖范围表示只在测试和编译classpath时有效,在运行时无效,换句话说就是该依赖不会被打进包中-->
<scope>provided</scope>
</dependency>
</dependencies>
<!-- 在properties标签中定义的值可以通过使用${key}在pom的任何位置访问,其中key为属性值 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<project.assembly.directory>src/main/resources/assembly</project.assembly.directory>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<!--该方式会将所有依赖打包到jar,生成的jar包带有jar-with-dependencies后缀 -->
<descriptorRefs>
<!-- 将依赖一起打包到 JAR -->
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- 该标签可以配置主main类,即 使该jar包成为可执行jar包,可在META-INF下的MF文件中找到Main-class一行 -->
<archive>
<manifest>
<mainClass></mainClass>
</manifest>
</archive>
</configuration>
<!-- 配置执行器,若还想增加编写新的插件,在此处新增执行器即可 -->
<executions>
<execution>
<!-- 执行器id -->
<id>plugin1</id>
<!-- 绑定到maven的package生命周期 -->
<phase>package</phase>
<goals>
<!-- 代表只运行一次 -->
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<!-- 描述文件的地址 -->
<descriptor>${project.assembly.directory}/assembly-plugin1.xml</descriptor>
</descriptors>
<!-- 自定义包名,如果不配置则是 artifactId + version + assemblyId,配置后则为 finalName + assemblyId,当然也可以增加属性去除自动拼接assemblyId值 -->
<finalName>multiPluginDemo</finalName>
</configuration>
</execution>
<execution>
<id>plugin2</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${project.assembly.directory}/assembly-plugin2.xml</descriptor>
</descriptors>
<finalName>multiPluginDemo</finalName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
其中打包脚本之一的assembly-plugin1.xml文件如下:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<!-- 文件id,与前面保持一致即可 -->
<id>plugin1</id>
<!-- 是否生成和压缩包同名的项目和目录 -->
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<!-- 指定格式 -->
<format>jar</format>
</formats>
<fileSets>
<fileSet>
<!-- 文件所在项目中的位置 -->
<directory>${project.build.outputDirectory}/qingcha/test/common</directory>
<!-- 打包后的展示路径,必须与包路径保持一致 -->
<outputDirectory>qingcha/test/common</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.build.outputDirectory}/qingcha/test/plugin1</directory>
<outputDirectory>qingcha/test/plugin1</outputDirectory>
</fileSet>
<fileSet>
<directory>src/main/resources/plugin1</directory>
<!-- 由于依赖spi机制,因此这里的输出路径需要满足条件,否则插件便不生效了 -->
<outputDirectory>META-INF/services</outputDirectory>
</fileSet>
</fileSets>
</assembly>
最终直接使用mvn package打包即可,可在target/ 目录下看到最终的jar包,多个plugin会有多个jar包:
如果还要增加一个plugin的话,可依次增加对应的实现类、提供者配置文件、脚本描述文件、执行器
关于properties标签题外话(maven的内置变量)
在上面的脚本描述文件中有使用到 ${project.build.outputDirectory} ,然后查看pom文件发现我们并没有定义该key值,因此也能猜到这是maven的内置变量,常用的内置变量如下:
- ${project.basedir}:这引用了module/project的根文件夹(当前pom.xml文件所在的位置),还可以简化的写法:${basedir}
- ${project.build.directory}:这表示默认的target文件夹。
- ${project.build.outputDirectory}:默认情况下表示target/classes文件夹。
- ${project.build.testOutputDirectory}:这表示默认的target/test-classes文件夹。
- ${project.build.sourceDirectory}:这表示默认情况下src/main/java文件夹。
- ${project.build.testSourceDirectory}:这表示默认情况下src/test/java文件夹。
- ${project.build.finalName}:默认情况下定义为${project.artifactId}-${project.version}。
- ${project.version}:这可以在必须编写文字版本的位置使用,否则,特别是如果您在多模块构建模块间依赖关系。
- ${settings.localRepository}:它引用了本地存储库的位置。这是默认的${home}/.m2/repository。