目錄
前言
有時候我們需要在一個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>
<!-- 配置執行器,若還想增加編寫新的插件,在此處新增執行器即可 -->
<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。