Maven整體認識——詳細介紹
前言
本文可以幫助你加深對Maven的整體認識,不是一篇基礎文章。如果你現在還沒有用 Maven 跑過 HelloWorld,那麽本文可能不適合你。
一、Maven簡介
Maven 官網:https://maven.apache.org
Maven 3.3.9版本文檔:http://maven.apache.org/ref/3...
Maven是一個項目管理工具,它包含了一個項目對象模型 (Project Object Model),一組標準集合,一個項目生命周期(Project Lifecycle),一個依賴管理系統(Dependency Management System),和用來運行定義在生命周期階段(phase)中插件(plugin)目標(goal)的邏輯。
-
版本:maven有自己的版本定義和規則
-
構建:可以完成編譯,打包,部署等。
-
依賴管理:方便引入所需依賴 Jar 包,不需手動下載
-
文檔生成:maven的site命令支持各種文檔信息的發布,包括構建過程的各種輸出,javadoc,產品文檔等。
-
項目關系:一個大型的項目通常有幾個小項目或者模塊組成,用maven可以很方便地管理
二、Maven生命周期
maven把項目的構建劃分為不同的生命周期(lifecycle)。粗略一點的話,它這個過程(phase)包括:
-
驗證(validate):驗證項目是否正確
-
編譯(compile): 編譯項目的源代碼
-
測試(test):使用合適的單元測試框架測試編譯的源代碼。這些測試不應該要求代碼被打包或部署
-
打包(package)
-
驗證(verify)
-
安裝(install)
-
部署(deploy)
maven中所有的執行動作(goal)都需要指明自己在這個過程中的執行位置,然後maven執行的時候,就依照過程的發展依次調用這些goal進行各種處理。
這個也是maven的一個基本調度機制。一般來說,位置稍後的過程都會依賴於之前的過程。當然,maven同樣提供了配置文件,可以依照用戶要求,跳過某些階段。
三、Maven 版本規範
maven使用如下幾個要素來唯一定位某一個輸出物: groupId:artifactId:packaging:version 。比如org.springframework:spring:2.5 。每個部分的解釋如下:
-
groupId 公司,團體等。如Apache Software的項目有以org.apache開頭的groupId。
-
artifactId 項目的唯一標識符。比如一個helloworld項目就叫helloworld。
-
packaging 項目打包輸出的類型,默認是jar。類型為war的項目產生一個web應用。
-
version 一個項目的特定版本。發布的項目有一個固定的版本標識來指向該項目的某一個特定的版本。而正在開發中的項目可以用一個特殊的標識,這種標識給版本加上一個"SNAPSHOT"的標記。
-
SNAPSHOT 如果一個版本包含字符串"SNAPSHOT",Maven就會在安裝或發布這個組件的時候將該符號展開為一個日期和時間值,轉換為UTC時間。例如,"1.0-SNAPSHOT"會在2010年5月5日下午2點10分發布時候變成1.0-20100505-141000-1。這個詞只能用於開發過程中,因為一般來說,項目組都會頻繁發布一些版本,最後實際發布的時候,會在這些snapshot版本中尋找一個穩定的,用於正式發布,比如1.4版本發布之前,就會有一系列的1.4-SNAPSHOT,而實際發布的1.4,也是從中拿出來的一個穩定版。
-
LATEST 指某個特定構件的最新發布,這個發布可能是一個發布版,也可能是一個snapshot版,具體看哪個時間最後。
-
RELEASE 指最後一個發布版。
-
maven有自己的版本規範,一般是如下定義
<major version>.<minor version>.<incremental version>-<qualifier>
,比如1.2.3-beta-01。要說明的是,maven自己判斷版本的算法是major,minor,incremental部分用數字比較,qualifier部分用字符串比較,所以要小心 alpha-2和alpha-15的比較關系,最好用 alpha-02的格式。 -
maven在版本管理時候可以使用幾個特殊的字符串 SNAPSHOT ,LATEST ,RELEASE 。比如"1.0-SNAPSHOT"。各個部分的含義和處理邏輯如下說明:
四、Maven插件機制
1. Maven默認插件
不配置Plugin時,Maven默認會使用以下插件。如果針對各個 plugin 有特殊配置的話,需要顯示指定 plugin 和 屬性配置。
plugin | function | life cycle phase |
---|---|---|
maven-clean-plugin | 清理上一次執行創建的target文件 | clean |
maven-resources-plugin | 處理資源文件 | resources,testResources |
maven-compiler-plugin | 編譯Java代碼 | compile、testCompile |
maven-surefire-plugin | 執行單元測試文件 | test |
maven-jar-plugin | 創建 jar | package |
maven-install-plugin | 拷貝jar到本地的maven倉庫 .m2/repository 下面 | install |
maven-deploy-plugin | 發布 jar | deploy |
maven-site-plugin | 生成文檔 | site |
maven-site-plugin:將工程所有文檔生成網站,生成的網站界面默認和apache的項目站點類似,但是其文檔用doxia格式寫的,目前不支持docbook,需要用其他插件配合才能支持。需要指出的是,在maven 2.x系列中和maven3.x的site命令處理是不同的,在舊版本中,用 mvn site 命令可以生成reporting節點中的所有報表,但是在maven3中,reporting過時了,要把這些內容作為 maven-site-plugin的configuration的內容才行。詳細內容可以參考http://www.wakaleo.com/blog/2...
<build>
<!-- resources 是 maven-resources-plugin 的-->
<resources>
<resource>
<directory>src/main/java</directory>
<filtering>true</filtering> <!-- filtering 用來表示資源文件中的占位符是否需要被profiles中的屬性動態替換,true為需要替換。 -->
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
<include>*.xml</include>
<include>*.dic</include>
<include>*.txt</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>*.p12</include>
</includes>
</resource>
</resources>
<plugins>
<!--
maven-compiler-plugin編譯源代碼。
指定maven編譯的jdk版本,如果不指定,maven3默認用jdk 1.5 maven2默認用jdk1.3
windows默認使用GBK編碼,java項目經常編碼為utf8,也需要在compiler插件中指出,否則中文亂碼可能會出現編譯錯
-->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!--
maven-resources-plugin用來處理資源文件,默認的主資源文件目錄是src/main/resources。
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins></build>
2. Maven常用插件
2.1 Tomcat插件
tomcat插件有兩種:tomcat-maven-plugin 和 tomcat7-maven-plugin,使用方式基本相同。
-
tomcat-maven-plugin 插件是org.codehaus.mojo組織提供的,裏面的tomcat是6.0.29版本,沒有更新了。
-
tomcat7-maven-plugin 插件是apache提供的,官網:http://tomcat.apache.org/mave...
-
tomcat7-maven-plugin 插件使用
<plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <path>/</path> <port>8080</port> <uriEncoding>UTF-8</uriEncoding> <server>tomcat7</server> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>run</goal> </goals> </execution> </executions></plugin>
命令:
tomcat7:deploy --部署一個web war包tomcat7:reload --重新加載web war包tomcat7:start --啟動tomcattomcat7:stop --停止tomcattomcat7:undeploy --停止一個war包tomcat7:run --啟動嵌入式tomcat ,並運行當前項目
-
tomcat-maven-plugin 插件使用
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>tomcat-maven-plugin</artifactId> <version>1.1</version> <configuration> <path>/helloworld</path> <port>8080</port> <uriEncoding>UTF-8</uriEncoding> <url>http://localhost:8080/manager/html</url> <server>tomcat6</server> <systemProperties> <JAVA_OPTS>-Xms256m -Xmx512m -XX:MaxPermSize=512m</JAVA_OPTS> </systemProperties> </configuration></plugin>
命令:
tomcat:deploy --部署一個web war包tomcat:reload --重新加載web war包tomcat:start --啟動tomcattomcat:stop --停止tomcattomcat:undeploy --停止一個war包tomcat:run --啟動嵌入式tomcat ,並運行當前項目
配置參數:
path:是訪問應用的路徑
port:是tomcat 的端口號
uriEncoding:URL按UTF-8進行編碼,這樣就解決了中文參數亂碼。
Server:指定tomcat名稱。
2.2 自動部署插件wagon
自動部署包含三個步驟:
編譯打包、上傳到服務器、在服務器上執行linux命令
2.2.1 文件上傳到服務器
Maven項目可使用 mvn install 指令打包,打包完成後包位於target目錄下,要想在遠程服務器上部署,首先要將包上傳到服務器。
首先在本地的setting.xml中配置server的信息,包括id,用戶名,密碼。(當然也可以在pom.xml裏面配置)
<servers>
<server>
<id>linux_server</id>
<username>user</username>
<password>password</password>
</server></servers>
pom.xml
<build>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>2.8</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>1.0</version>
<configuration>
<serverId>linux_server</serverId>
<fromFile>target/test.war</fromFile>
<url>scp://user:[email protected]/home/tomcat7/webapps</url>
</configuration>
</plugin>
</plugins></build>
<serverId>linux_server</serverId>
: 在setting.xml中配置的server的id名字<fromFile>target/test.war</fromFile>
:是要上傳到服務器的文件,一般來說是jar或者war包<url>scp://user:[email protected]/home/tomcat7/webapps</url>
:配置服務器的用戶、密碼、地址以及文件上傳的目錄
命令:
# 對項目進行打包和上傳操作mvn clean install wagon:upload-single
如果覺的wagon命令太長,可以設置 excutions 來配置phase和goals來簡化命令。
2.2.2 在服務器上執行linux命令
1. 運行jar文件
<build>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>2.8</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>1.0</version>
<configuration>
<fromFile>target/test.jar</fromFile>
<url>scp://user:[email protected]/home/java/exe</url>
<commands>
<command>pkill -f test.jar</command> <!-- 殺死原來的進程 -->
<command>nohup java -jar /home/java/exe/test.jar</command> <!-- 重新啟動test.jar-->
</commands>
<displayCommandOutputs>true</displayCommandOutputs> <!-- 顯示運行命令的輸出結果 -->
</configuration>
</plugin>
</plugins></build>
命令
<!--install、wagon:upload-single、wagon:sshexec 分別對項目進行打包、上傳、運行command命令的操作-->mvn clean install wagon:upload-single wagon:sshexec
2. 上傳war包並啟動Tomcat
<build>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>2.8</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>1.0</version>
<configuration>
<fromFile>target/javawebdeploy.war</fromFile>
<url>scp://user:[email protected]/home/tomcat7/webapps</url>
<commands>
<!-- 重啟Tomcat -->
<command>sh /home/tomcat7/bin/shutdown.sh</command>
<command>rm -rf /home/tomcat7/webapps/test</command>
<command>sh /home/tomcat7/bin/startup.sh</command>
</commands>
<displayCommandOutputs>true</displayCommandOutputs>
</configuration>
</plugin>
</plugins></build>
命令
mvn clean install wagon:upload-single wagon:sshexec
2.2.3 配置execution
如果覺得 mvn clean package wagon:upload-single wagon:sshexec
命令太長了不好記,那麽可以配置execution,在運行deploy的同時運行upload-single和sshexec。
<build>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>2.8</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>upload-deploy</id>
<!-- 運行deploy命令時同時運行upload-single和sshexec -->
<phase>deploy</phase>
<goals>
<goal>upload-single</goal>
<goal>sshexec</goal>
</goals>
<configuration>
<fromFile>target/test.war</fromFile>
<url>scp://user:[email protected]/home/tomcat7/webapps</url>
<commands>
<command>sh /home/tomcat7/bin/shutdown.sh</command>
<command>rm -rf /coder/tomcat7/webapps/test</command>
<command>sh /coder/tomcat7/bin/startup.sh</command>
</commands>
<displayCommandOutputs>true</displayCommandOutputs>
</configuration>
</execution>
</executions>
</plugin>
</plugins></build>
命令
<!-- 即可使用mvn clean package來代替mvn clean package wagon:upload-single wagon:sshexec -->mvn clean deploy
2.2.4. 完整示例配置
首先在本地的setting.xml中配置server的信息,包括id,用戶名,密碼。(當然也可以在pom.xml裏面配置)
<servers>
<server>
<id>linux_server</id>
<username>user</username>
<password>password</password>
</server></servers>
pom.xml
<build>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>2.8</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>1.0</version>
<configuration>
<serverId>linux_server</serverId>
<url>scp://user:[email protected]/home/tomcat7/webapps</url>
<displayCommandOutputs>true</displayCommandOutputs> <!-- 顯示運行命令的輸出結果 -->
</configuration>
<executions>
<!-- 將war包上傳到服務器並重啟服務器 -->
<execution>
<id>upload-war-to-server</id>
<phase>deploy</phase>
<goals>
<goal>upload-single</goal>
<goal>sshexec</goal>
</goals>
<configuration>
<fromFile>target/test.war</fromFile>
<commands>
<command>datefilename=$(date +%Y%m%d-%H%M%S);cp /home/tomcat7/webapps/test.war /home/tomcat7/webapps/test.war.$datefilename</command> <!--備份舊的war包-->
<command>ps -ef | grep /home/tomcat7/ | grep -v grep | awk {‘print $2‘} | sed -e "s/^/kill -9 /g" | sh</command> <!-- 關閉tomcat7 -->
<command>rm -rf /home/tomcat7/webapps/test</command> <!-- 刪除test項目 -->
<command>export JAVA_HOME=/home/jdk/jdk1.8.0_91;sh /home/tomcat7/bin/startup.sh</command> <!-- 啟動tomcat -->
</commands>
</configuration>
</execution>
</plugin>
</plugins></build>
命令
mvn clean deploy
五、Maven 項目依賴
1. 多模塊依賴和繼承
項目結構圖:
parent
├─childA(model層)
│ └─pom.xml(jar)
├─childB(web層)
│ └─pom.xml(war)
└─pom.xml(pom)
-
parent中執行
mvn install
就能將 childA和childB 一起編譯parent的pom.xml做如下配置:
<groupId>com.song</groupId><artifactId>parent</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging> <!-- pom表示它是一個被繼承的模塊 --><modules> <module>childA</module> <!-- 不加module則不會被聯合編譯 --> <module>childB</module></modules>
childA和childB的pom.xml都需要配置parent,防止引入的包沖突(如果不加parent,會分別去編譯他們引入的依賴,會重復引入包):
<!-- childA 的 pom.xml--><parent> <artifactId>parent</artifactId> <groupId>com.song</groupId> <version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>childA</artifactId><packaging>jar</packaging><!-- childB 的 pom.xml--><parent> <artifactId>parent</artifactId> <groupId>com.song</groupId> <version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>childB</artifactId><packaging>war</packaging>
-
子pom間存在引用關系,比如childB引用到了childA的jar包
<dependency>
<groupId>com.module</groupId>
<artifactId>childA</artifactId> <!--加上childA的依賴-->
<version>1.0-SNAPSHOT</version></dependency>
2. 子項目繼承父項目的依賴
parent中加上<dependencyManagement>
,child項目就可以繼承parent項目的依賴,並且在child中可以不用加version了。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
</dependencies></dependencyManagement>
3. 依賴範圍
如果不顯示執行 <scope> 屬性時,默認 <scope>compile</scope>
。
scope 屬性包括:
-
compile(編譯範圍):編譯範圍的
<dependency>
在所有的classpath中可用,同時它們也會被打包 -
provided(已提供範圍):表示部署的環境當中有某容器已經提供了該jar包,只在編譯classpath(不是運行時)可用。它們不是傳遞性的,也不會被打包。例如,如果你開發了一個web應用,你可能在編譯classpath中需要可用的Servlet API來編譯一個servlet,但是你不會想要在打包好的WAR中包含這個Servlet API;這個Servlet API JAR由你的servlet容器(Tomcat)提供。
-
runtime(運行時範圍):只在運行和測試系統的時候需要,但在編譯的時候不需要。
-
test(測試範圍):在一般的 編譯和運行時都不需要,它們只有在測試編譯和測試運行階段可用。
-
system (系統範圍):該範圍不推薦使用(你應該一直盡量去從公共或定制的Maven倉庫中引用依賴)
詳細可參考:https://maven.apache.org/guid...
六、Maven profiles切換測試環境和正式環境
<profiles>
<profile>
<!-- 本地開發環境 -->
<id>dev</id>
<properties>
<profiles.active>dev</profiles.active>
</properties>
<activation>
<!-- 設置默認激活這個配置 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<!-- 發布環境 -->
<id>release</id>
<properties>
<profiles.active>release</profiles.active>
</properties>
</profile>
<profile>
<!-- 測試環境 -->
<id>beta</id>
<properties>
<profiles.active>beta</profiles.active>
</properties>
</profile></profiles> <build>
<finalName>helloworld</finalName>
<resources>
<!-- 先全部不包含 -->
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>config/</exclude>
</excludes>
</resource>
<!-- 再指定需要包含的文件夾 -->
<resource>
<directory>src/main/resources/config/${profiles.active}</directory>
<targetPath>.</targetPath>
</resource>
</resources></build>
id代表這個環境的唯一標識,在 mvn install -Pdev 來指定。
此properties定義了三個環境,分別是dev(開發環境)、beta(測試環境)、release(發布環境)
activeByDefault=true代表如果不指定某個固定id的profile,那麽就使用這個環境
使用 mvn install -Pdev
會將 id 為 dev 的 profile 中的<properties>
定義的屬性profiles.active
自動替換${profiles.active}
占位符的變量。最終build到classpath的資源文件由maven-resources-plugin來指定,為src/main/resources/config/dev文件下的所有文件。
七、Maven 變量
1. 內置屬性
-
${basedir} represents the directory containing pom.xml
-
**${version}** equivalent to ${project.version } or ${pom.version }
2. Pom/Project properties
所有pom中的元素都可以用 project. 前綴進行引用,以下是部分常用的
-
**${project.build.directory}** results in the path to your "target" dir, this is the same as ${pom.project.build.directory}
-
${project.build.outputDirectory} results in the path to your "target/classes" dir
-
${project.name} refers to the name of the project.
-
${project.version} refers to the version of the project.
-
${project.build.finalName} refers to the final name of the file created when the built project is packaged
3. 本地用戶設定
所有用的的 settings.xml 中的設定都可以通過 settings. 前綴進行引用
-
${settings.localRepository} refers to the path of the user‘s local repository.
-
${maven.repo.local} also works for backward compatibility with maven1
4. 環境變量
系統的環境變量通過 env. 前綴引用
-
${env.M2_HOME} returns the Maven2 installation path.
-
**${java.home}** specifies the path to the current JRE_HOME environment use with relative paths to get for example: <jvm>${java.home}../bin/java.exe</jvm>
5. java系統屬性
所有JVM中定義的java系統屬性.
6. pom.xml自定義變量
<project>
...
<properties>
<project.build.finalName>hellowolrld</project.build.finalName>
</properties>
...
</project>
則引用 ${project.build.finalName} 就會得到值 hellowolrld
7. parent 工程的變量
parent工程的pom.xml中的變量用前綴 ${project.parent}
引用. 上級工程的版本也可以這樣引用: ${parent.version }
.
參考文章:
https://blog.csdn.net/wwbmyos...
https://blog.csdn.net/j080624...
http://xxgblog.com/2015/10/23...
https://blog.csdn.net/java_an...
Maven整體認識——詳細介紹