這裡給大家詳細說一下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
本文出自博客園,歡迎大家加入博客園。