(十三)Maven插件解析運行機制

来源:http://www.cnblogs.com/AlanLee/archive/2016/12/21/6208562.html
-Advertisement-
Play Games

這裡給大家詳細說一下Maven的運行機制,讓大家不僅知其然,更知其所以然。 1.插件保存在哪裡? 與我們所依賴的構件一樣,插件也是基於坐標保存在我們的Maven倉庫當中的。在用到插件的時候會先從本地倉庫查找插件,如果本地倉庫沒有則從遠程倉庫查找插件並下載到本地倉庫。 與普通的依賴構件不同的是,Mav ...


這裡給大家詳細說一下Maven的運行機制,讓大家不僅知其然,更知其所以然。

 

1.插件保存在哪裡?

與我們所依賴的構件一樣,插件也是基於坐標保存在我們的Maven倉庫當中的。在用到插件的時候會先從本地倉庫查找插件,如果本地倉庫沒有則從遠程倉庫查找插件並下載到本地倉庫。

與普通的依賴構件不同的是,Maven會區別對待普通依賴的遠程倉庫與插件的遠程倉庫。前面提到的配置遠程倉庫只會對普通的依賴有效果。當Maven需要的插件在本地倉庫不存在時是不會去我們以前配置的遠程倉庫查找插件的,而是需要有專門的插件遠程倉庫,我們來看看怎麼配置插件遠程倉庫,在pom.xml加入如下內容:

 1 <pluginRepositories>
 2         <pluginRepository>
 3             <id>nexus</id>
 4             <name>nexus</name>
 5             <url>http://192.168.0.70:8081/content/groups/public/</url>
 6             <releases>
 7                 <enabled>true</enabled>
 8             </releases>
 9             <snapshots>
10                 <enabled>true</enabled>
11             </snapshots>
12         </pluginRepository>
13 </pluginRepositories>

大家可以發現,除了pluginRepositories和pluginRepository與以前配置遠程倉庫不同以外,其他的都是一樣的,所代表的含義也是一樣的。Maven的父POM中也是有內置一個插件倉庫的,我現在用的電腦安裝的是Maven 3.0.4版本,我們可以找到這個文件:${M2_HOME}/lib/maven-model-builder-3.0.4.jar,打開該文件,能找到超級父POM:\org\apache\maven\model\pom-4.0.0.xml,它是所有Maven POM的父POM,所有Maven項目都繼承該配置。


我們來看看預設的遠程插件倉庫配置的是啥:

 1 <pluginRepositories>
 2     <pluginRepository>
 3       <id>central</id>
 4       <name>Central Repository</name>
 5       <url>http://repo.maven.apache.org/maven2</url>
 6       <layout>default</layout>
 7       <snapshots>
 8         <enabled>false</enabled>
 9       </snapshots>
10       <releases>
11         <updatePolicy>never</updatePolicy>
12       </releases>
13     </pluginRepository>
14 </pluginRepositories>

預設插件倉庫的地址就是中央倉庫咯,它關閉了對snapshots的支持,防止引入snapshots版本的插件而導致不穩定的構件。一般來說,中央倉庫所包含的插件完全能夠滿足我們的需要,只有在少數情況下才要配置,比如項目的插件無法在中央倉庫找到,或者自己編寫了插件才會配置自己的遠程插件倉庫。

 

2.插件命令運行解析

我們來看這樣一個命令:

mvn compiler:compiler

這個命令會調用maven-compiler-plugin插件並執行compiler目標,大家有木有覺得很神奇?我們在pom.xml中配置插件往往是這樣:

1         <plugin>
2             <groupId>org.apache.maven.plugins</groupId>
3             <artifactId>maven-compiler-plugin</artifactId>
4             <version>3.1</version>
5             <configuration>
6                 <source>1.7</source> <!-- 源代碼使用的開發版本 -->
7                 <target>1.7</target> <!-- 需要生成的目標class文件的編譯版本 -->
8             </configuration>
9         </plugin>    

maven-compiler-plugin插件預設執行的目標為compiler,那麼命令的完整寫法應該是:mvn org.apache.maven.plugins:maven-compiler-plugin:3.1:compiler才對啊,為什麼mvn compiler:compiler也能完美的執行?

 

我們來看看Maven到底幹了些神馬來做到如此牛逼的功能:

 

①插件預設groupId

Maven預設以org.apache.maven.plugins作為groupId,到這裡我們的命令應該是長這樣的:

mvn org.apache.maven.plugins:compiler:compiler

我們也可以配置自己預設的groupId,在Maven的settings.xml中添加如下內容,前面提過最好將settings.xml放在用戶目錄的.m2下:

1 <pluginGroups>
2     <!-- pluginGroup
3      | Specifies a further group identifier to use for plugin lookup.
4     <pluginGroup>com.your.plugins</pluginGroup>
5     -->
6     <pluginGroup>com.your.plugins</pluginGroup>
7 </pluginGroups>

不過說實在的,沒必要動他就別去動他了,我們用Maven只是解決一些剛需的問題,沒必要的設置就儘量不去動他,別把Maven搞得太複雜,雖然Maven的卻有點小複雜,跟大家扯這些只是希望大家能夠對maven理解的更深入那麼一點點,並不是建議大家一定要去使用某些東西,大家在平時的開發中要謹記這一點。

 

②我們來看看Maven插件遠程倉庫的元數據org/apache/maven/plugins/maven-metadata.xml,Maven預設的遠程倉庫是http://repo.maven.apache.org/maven2/,所有插件元數據路徑則是:http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml,我們找到compiler插件的元數據,如圖:

這裡會根據prefix指定的首碼找到對應的artifactId,到這裡我們的命令應該長成了這樣:

mvn org.apache.maven.plugins:maven-compiler-plugin:compiler

 

③我們再根據groupId和artifactId找到maven-compiler-plugin插件單個的元數據,路徑為http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-compiler-plugin/maven-metadata.xml,如圖:

maven將所有的遠程插件倉庫及本地倉庫元數據歸併後,就能找到release的版本(maven3後為了保證項目構建的穩定性預設使用release版本),到這裡命令就被擴展成為這樣:

mvn org.apache.maven.plugins:maven-compiler-plugin:3.6.0:compiler

如果執行的是mvn compiler:compiler命令,由於maven-compiler-plugin的最新版本已經到了3.6.0,則預設會使用此版本。最後的compiler則是插件要執行的目標咯,看到這裡大家應該明白mvn compiler:compiler命令為什麼能夠得到完美的運行了吧。

 

3.Maven超級POM

最後給大家把超級父POM貼出來,再次強調,如果我們沒有在自己的pom.xml中配置相應的內容,則預設會使用超級父POM配置的內容。我現在用的電腦安裝的是Maven 3.0.4版本,我們可以找到這個文件:${M2_HOME}/lib/maven-model-builder-3.0.4.jar,打開該文件,能找到超級父POM:\org\apache\maven\model\pom-4.0.0.xml,它是所有Maven POM的父POM,所有Maven項目都繼承該配置。

  1 <?xml version="1.0" encoding="UTF-8"?>
  2 
  3 <!--
  4 Licensed to the Apache Software Foundation (ASF) under one
  5 or more contributor license agreements.  See the NOTICE file
  6 distributed with this work for additional information
  7 regarding copyright ownership.  The ASF licenses this file
  8 to you under the Apache License, Version 2.0 (the
  9 "License"); you may not use this file except in compliance
 10 with the License.  You may obtain a copy of the License at
 11 
 12     http://www.apache.org/licenses/LICENSE-2.0
 13 
 14 Unless required by applicable law or agreed to in writing,
 15 software distributed under the License is distributed on an
 16 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17 KIND, either express or implied.  See the License for the
 18 specific language governing permissions and limitations
 19 under the License.
 20 -->
 21 
 22 <!-- START SNIPPET: superpom -->
 23 <project>
 24   <modelVersion>4.0.0</modelVersion>
 25 
 26   <repositories>
 27     <repository>
 28       <id>central</id>
 29       <name>Central Repository</name>
 30       <url>http://repo.maven.apache.org/maven2</url>
 31       <layout>default</layout>
 32       <snapshots>
 33         <enabled>false</enabled>
 34       </snapshots>
 35     </repository>
 36   </repositories>
 37 
 38   <pluginRepositories>
 39     <pluginRepository>
 40       <id>central</id>
 41       <name>Central Repository</name>
 42       <url>http://repo.maven.apache.org/maven2</url>
 43       <layout>default</layout>
 44       <snapshots>
 45         <enabled>false</enabled>
 46       </snapshots>
 47       <releases>
 48         <updatePolicy>never</updatePolicy>
 49       </releases>
 50     </pluginRepository>
 51   </pluginRepositories>
 52 
 53   <build>
 54     <directory>${project.basedir}/target</directory>
 55     <outputDirectory>${project.build.directory}/classes</outputDirectory>
 56     <finalName>${project.artifactId}-${project.version}</finalName>
 57     <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
 58     <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
 59     <scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
 60     <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
 61     <resources>
 62       <resource>
 63         <directory>${project.basedir}/src/main/resources</directory>
 64       </resource>
 65     </resources>
 66     <testResources>
 67       <testResource>
 68         <directory>${project.basedir}/src/test/resources</directory>
 69       </testResource>
 70     </testResources>
 71     <pluginManagement>
 72       <!-- NOTE: These plugins will be removed from future versions of the super POM -->
 73       <!-- They are kept for the moment as they are very unlikely to conflict with lifecycle mappings (MNG-4453) -->
 74       <plugins>
 75         <plugin>
 76           <artifactId>maven-antrun-plugin</artifactId>
 77           <version>1.3</version>
 78         </plugin>
 79         <plugin>
 80           <artifactId>maven-assembly-plugin</artifactId>
 81           <version>2.2-beta-5</version>
 82         </plugin>
 83         <plugin>
 84           <artifactId>maven-dependency-plugin</artifactId>
 85           <version>2.1</version>
 86         </plugin>
 87         <plugin>
 88           <artifactId>maven-release-plugin</artifactId>
 89           <version>2.0</version>
 90         </plugin>
 91       </plugins>
 92     </pluginManagement>
 93   </build>
 94 
 95   <reporting>
 96     <outputDirectory>${project.build.directory}/site</outputDirectory>
 97   </reporting>
 98 
 99   <profiles>
100     <!-- NOTE: The release profile will be removed from future versions of the super POM -->
101     <profile>
102       <id>release-profile</id>
103 
104       <activation>
105         <property>
106           <name>performRelease</name>
107           <value>true</value>
108         </property>
109       </activation>
110 
111       <build>
112         <plugins>
113           <plugin>
114             <inherited>true</inherited>
115             <artifactId>maven-source-plugin</artifactId>
116             <executions>
117               <execution>
118                 <id>attach-sources</id>
119                 <goals>
120                   <goal>jar</goal>
121                 </goals>
122               </execution>
123             </executions>
124           </plugin>
125           <plugin>
126             <inherited>true</inherited>
127             <artifactId>maven-javadoc-plugin</artifactId>
128             <executions>
129               <execution>
130                 <id>attach-javadocs</id>
131                 <goals>
132                   <goal>jar</goal>
133                 </goals>
134               </execution>
135             </executions>
136           </plugin>
137           <plugin>
138             <inherited>true</inherited>
139             <artifactId>maven-deploy-plugin</artifactId>
140             <configuration>
141               <updateReleaseInfo>true</updateReleaseInfo>
142             </configuration>
143           </plugin>
144         </plugins>
145       </build>
146     </profile>
147   </profiles>
148 
149 </project>
150 <!-- END SNIPPET: superpom -->

很多插件是超級父POM當中並沒有配置的,如果用戶使用某個插件時沒有設定版本,那麼則會根據我上述所說的規則去倉庫中查找可用的版本,然後做出選擇。在Maven2中,插件的版本會被解析至latest。也就是說,當用戶使用某個非核心插件且沒有聲明版本的時候,Maven會將版本解析為所有可用倉庫中的最新版本,latest表示的就是最新版本,而這個版本很有可能是快照版本。

當插件為快照版本時,就會出現潛在的問題。昨天還好好的,可能今天就出錯了,其原因是這個快照版本發生了變化導致的。為了防止這類問題,Maven3調整瞭解析機制,當插件沒有聲明版本的時候,不再解析至latest,而是使用release。這樣就避免了由於快照頻繁更新而導致的不穩定問題。但是這樣就好了嗎?不寫版本號其實是不推薦的做法,例如,我使用的插件發佈了一個新版本,而這個release版本與之前的版本的行為發生了變化,這種變化依然可能導致我們項目的癱瘓。所以使用插件的時候,應該一直顯式的設定版本,這也解釋了Maven為什麼要在超級父POM中為核心插件設定版本咯。

 

結束語:當你感到悲哀痛苦時,最好是去學些什麼東西,學習會使你從悲哀痛苦中走出來,學習會使你永遠立於不敗之地。說實在的,不要太在意眼前所發生的一切,更重要的是培養自己的個人能力,如今待在公司亦或者跳槽,決定你能不能繼續走下去的一定是你的個人能力,作為年輕人,在公司更看重的不應該是薪水的高低,而是公司能給你帶來多大的成長環境。找個好的公司其實不比找個合適的女朋友簡單,作為年輕人我們一定要不斷的提升個人能力,就跟找女朋友似的,往往就是你越有本事就越能夠不將就,你個人能力越強則越有選擇公司的資本。

 

可愛博主:AlanLee

博客地址:http://www.cnblogs.com/AlanLee

本文出自博客園,歡迎大家加入博客園。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 你真的懂異常(Exception)嗎? 目錄 異常介紹 異常的特點 怎樣使用異常 處理異常的 try-catch-finally 捕獲異常的 Catch 塊 釋放資源的 Finally 塊 捕獲異常的 Catch 塊 釋放資源的 Finally 塊 一、異常介紹 我們平時在寫程式時,無意中(或技術不 ...
  • 隨著公司業務的發展,網站的日活數也逐漸增多,以前只需要考慮將所需要的功能實現就行了,當日活越來越大的時候,就需要考慮對伺服器的資源使用消耗情況有一個清楚的認知。 最近老是發現資料庫的連接數如果幾天不重啟伺服器,就經常會發現有很多sleep很久的資料庫連接,對資料庫伺服器的性能有較大的影響。所以需要知 ...
  • 一.簡介 在網頁應用中,你經常需要在處理完表單或其它類型的用戶輸入後,顯示一個通知消息(也叫做“flash message”)給用戶 對於這個功能,Django 提供基於Cookie 和會話的消息,無論是匿名用戶還是認證的用戶。 其消息框架允許你臨時將消息存儲在請求中,併在接下來的請求(通常就是下一 ...
  • 線程可以理解為下載的通道,一個線程就是一個文件的下載通道,多線程也就是同時開啟好幾個下載通道。當伺服器提供下載服務時,使用下載者是共用帶寬的,在優先順序相同的情況下,總伺服器會對總下載線程進行平均分配。不難理解,如果你線程多的話,那下載的越快。 現流行的下載軟體都支持多線程,且支持中途暫停下載,再次開 ...
  • 如果運行後如圖的錯,需要進行如下操作來解決: a:打開cmd,輸入netstat -ano 找到本地地址為8080的最後一項的數字,這個數字就是埠號。 b:再輸入taskkill /t /pid 埠號數字 /f 來關閉此進程。 c:註意每個命令後面不要加 ; 結尾,運行以上命令再重新運行工程即可 ...
  • 本文地址 可以拜讀: 從零開始學 Java 分享提綱: 1.java數據結構 1. java數據結構 1)【概述】 Java工具包提供了強大的數據結構。在Java中的數據結構主要包括以下幾種介面和類: 枚舉(Enumeration) 位集合(BitSet) 向量(Vector) 棧(Stack) 字 ...
  • 1、sdk返回值不是int型 1.1 登錄函數調用 def login(ip, port, username, password, device_info, error_code):"""LLONG CLIENT_Login(char *pchDVRIP, WORD wDVRPort,char *p... ...
  • 其實也沒啥好說的 用樹狀數組可以O(logn)的查詢 套一層整體二分就可以做到O(nlngn) 最後用樹鏈剖分讓序列上樹 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...