寫在前面:
- 你好,歡迎關注!
- 我熱愛技術,熱愛分享,熱愛生活, 我始終相信:技術是開源的,知識是共享的!
- 博客裏面的內容大部分均爲原創,是自己日常的學習記錄和總結,便於自己在後面的時間裏回顧,當然也是希望可以分享 自己的知識。如果你覺得還可以的話不妨關注一下,我們共同進步!
- 個人除了分享博客之外,也喜歡看書,寫一點日常雜文和心情分享,如果你感興趣,也可以關注關注!
- 公衆號:傲驕鹿先生
目錄
一、Maven流行插件
Maven 中項目的構建生命週期只是 Maven 根據實際情況抽象提煉出來的一個統一標準和規範,是不能做具體事情的。也就是說,Maven 沒有提供一個編譯器能在編譯階段編譯源代碼。既然 Maven 不做具體事情,那具體事情由誰做呢?好的思想、創意,最終都需要在做具體事情的實踐中執行纔有結果。
所以 Maven 只是規定了生命週期的各個階段和步驟,具體事情,由集成到 Maven 中的插件完成,就是由 maven-site-plugin 插件完成的。
Maven 在項目的構建過程中,只是在方向和步驟上面起到了管理和協調的作用。
Maven 在生命週期的每個階段都設計了插件接口。用戶可以在接口上根據項目的實際需要綁定第三方的插件,做該階段應該完成的任務,從而保證所有 Maven 項目構建過程的標準化。當然,Maven 對大多數構建階段綁定了默認的插件,通過這樣的默認綁定,又簡化和穩定了實際項目的構建。
Maven插件的基本概念能幫助我們理解maven的工作機制,但是高效的使用Maven避免不了使用插件,接來下就看一些常用的:
1、maven-assembly-plugin
該插件允許用戶整合項目的輸出,包括依賴,模塊,網站文檔和其他文檔到一個單獨的文檔,即可用定製化打包。
創建的文檔格式包括:zip, tar, tar.gz(tgz), gar.bz2(tbgz2), jar, dir,war 等等。四種預定義的描述器可用:bin, jar-with-dependencies, src, project.
(1)打包獨立運行的jar文件
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<!-- 配置main方法入口程序 -->
<mainClass>org.chench.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
特別注意: 如果在項目中使用了Spring框架,在通過maven-assembly-plugin打包成獨立可執行的jar包後,在執行時可能報如下錯誤:
Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace
這其實是maven-assembly-plugin的一個BUG,解決方案:使用maven-shade-plugin插件進行打包。
(2)打包壓縮文件
maven-assembly-plugin插件除了可以打包項目爲可獨立運行的jar文件,還可以將項目打包爲壓縮文件。
<!-- 部署打包: 通過maven-assembly插件壓縮爲tar包進行發佈 -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<executions>
<!-- 配置執行器 -->
<execution>
<id>assembly</id>
<!--綁定到package生命週期-->
<phase>package</phase>
<goals>
<!--只運行一次-->
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<attach>false</attach>
<descriptors>
<!--配置描述文件路徑-->
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
<finalName>${project.name}-${project.version}</finalName>
<outputDirectory>${basedir}/release</outputDirectory>
</configuration>
</plugin>
assembly.xml配置
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>distribution</id>
<formats>
<!-- 壓縮包格式 -->
<format>tar.gz</format>
<!-- <format>zip</format> -->
</formats>
<!-- 打包文件參數配置 -->
<fileSets>
<!-- 腳本 -->
<fileSet>
<directory>${basedir}/src/main/bin</directory>
<outputDirectory>bin</outputDirectory>
<includes>
<include>*.bat</include>
<include>*.sh</include>
</includes>
<fileMode>0755</fileMode>
</fileSet>
<!-- sql文件 -->
<fileSet>
<directory>${basedir}/src/main/sql</directory>
<outputDirectory>sql</outputDirectory>
<includes>
<include>*.sql</include>
</includes>
</fileSet>
<!-- jdbc.properties, logback.xml -->
<fileSet>
<directory>${basedir}/src/main/resources/profiles/${profile.dir}</directory>
<outputDirectory>conf</outputDirectory>
<includes>
<include>jdbc.properties</include>
<include>logback.xml</include>
</includes>
</fileSet>
<!-- INSTALL,README,change.log -->
<fileSet>
<directory>${basedir}</directory>
<outputDirectory></outputDirectory>
<includes>
<include>INSTALL</include>
<include>README.md</include>
<include>change.log</include>
</includes>
</fileSet>
<!-- 日誌目錄 -->
<fileSet>
<directory>target</directory>
<outputDirectory>logs</outputDirectory>
<excludes>
<exclude>**/*</exclude>
</excludes>
</fileSet>
<!-- 臨時目錄 -->
<fileSet>
<directory>target</directory>
<outputDirectory>temp</outputDirectory>
<excludes>
<exclude>**/*</exclude>
</excludes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<excludes>
<exclude>junit:junit</exclude>
</excludes>
</dependencySet>
</dependencySets>
<includeBaseDirectory>true</includeBaseDirectory>
<baseDirectory>${project.name}-${project.version}</baseDirectory>
</assembly>
2、maven-shade-plugin
打包可獨立運行的jar文件
<!-- 打包可執行jar文件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.chench.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
3、maven-dependency-plugin
通過該插件可以對被依賴組件進行復制,解壓等一系列操作。
場景一: 在Maven多模塊化項目中,可以使用maven-dependency-plugin將被依賴模塊jar文件中class文件提取出來放在指定位置。
<!-- 將依賴模塊的jar包文件提取出來放到指定位置 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.xxx</groupId>
<artifactId>xxx-xxx</artifactId>
<version>1.0.0</version>
<type>jar</type>
<includes>**/*.class</includes>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
場景二:將scope爲system的依賴jar包一起打包
<!-- 打包scope爲system的jar包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
<configuration>
<includeScope>system</includeScope>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</plugin>
場景三:將scope爲system的依賴jar包中的class文件解壓出來重新打包
<!-- 將scope爲system的依賴jar包中的class文件解壓出來重新打包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>unpack</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
</execution>
</executions>
<configuration>
<includeScope>system</includeScope>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</plugin>
4、maven-compiler-plugin
打包時設置編譯參數。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source> <!-- 源代碼使用的JDK版本 -->
<target>1.8</target> <!-- 需要生成的目標class文件的編譯版本 -->
<encoding>UTF-8</encoding><!-- 字符集編碼 -->
<skipTests>true</skipTests><!-- 跳過測試 -->
</configuration>
</plugin>
5、maven-resources-plugin
maven默認使用該maven-resources-plugin資源文件,不需要明確配置。
<resources>
<resource>
<!-- 指定資源目錄 -->
<directory>src/main/resources</directory>
<!-- 不打包指定類型的資源 -->
<excludes>
<exclude>**/*.svn</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources/profiles/${profile.dir}</directory>
<includes>
<include>*.properties</include>
</includes>
</resource>
</resources>
6、maven-jar-plugin
https://maven.apache.org/plugins/maven-jar-plugin/usage.html
使用該插件可以在打包jar文件時做一些事情,比如:定義MANIFEST.MF文件,過濾文件等。
<!-- 生成jar包時打包資源文件配置 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<excludes>
<exclude>**/profiles/**</exclude>
<exclude>**/jdbc.properties</exclude>
<exclude>**/*.proto</exclude>
</excludes>
</configuration>
</plugin>
7、maven-source-plugin
https://maven.apache.org/plugins/maven-source-plugin/usage.html
打包項目源碼。
<!-- 打包源碼 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
二、手寫Maven插件
Maven 作爲一個優秀的項目管理工具,其插件機制爲其功能擴展提供了非常大的便捷性。雖然說大多數情況下,我們可能不太會自己去編寫 Maven 插件,但不排除在某些特殊的情況下,我們需要去完成一個自己的插件,來協助我們處理某些比較通用的事情。
1.Maven 插件的命名規範
按照官方建議,maven插件的命名建議爲xxxx-maven-plugin,這樣命名有兩個好處
1、maven-xxxx-plugin爲maven官方插件命名,使用這種命名方式可能侵權
2、自定義插件maven執行命令爲mvn groupId:artifactId:goal,使用推薦命名方式,maven命令可以簡化爲mvn xxxx:goal
2.什麼是 Mojo?
Mojo 就是Maven plain Old Java Object。每一個 Mojo 就是 Maven 中的一個執行目標(executable goal),而插件則是對單個或多個相關的 Mojo 做統一分發。一個 Mojo 包含一個簡單的 Java 類。插件中多個類似 Mojo 的通用之處可以使用抽象父類來封裝。
3.創建MoJo工程
1、創建maven工程,選擇類型爲mojo
2、指定groupId、artifactId、版本號
3.在pom文件中指定打包類型爲maven-plugin
4、添加依賴
5、創建mojo實現類,該實現類繼承自AbstractMojo
注意這裏要通過@Mojo註解指定插件goalPrefix,否則插件無法生成成功
6、mvn clean install生成插件
4、測試自定義插件
1、創建maven過程
注意:一定要指定執行階段,否則插件無法正常運行
2、執行mvn Mojo:mojo,看到正常調用自定義Mojo
至此,一個簡單的Maven Plugin插件就編寫完成了。大家可以在熟悉這個操作的基礎上編寫自己的需求代碼。