Maven的基礎了解與使用


首發日期:2018-11-04


Maven的介紹:

什么是Maven:

  • Maven是apache旗下的一個java開源項目。
  • Maven是一個項目管理工具,它可以幫助我們管理項目
  • 可以使用Maven對java項目進行項目構建(構建包括清理、編譯、測試、報告、打包、部署六個過程,你可以認為是一個項目的從代碼到完整可運行項目的過程)、依賴管理。

為什么要學習maven?

以一個例子說一下maven的好處,說了它的好處,

1.maven可以幫我們管理依賴。在以往的時候,我們都是手動的導入jar包,然后build path;在導入jar包之前,我們需要去查找有哪些包,需要哪些包,這是一個非常繁雜的問題,如果你不是“老司機”的話,你可能會遺漏某些jar包;而在maven中,我們可以使用pom.xml來聲明需要哪些依賴包,然后maven就會根據pom.xml中的信息去獲取倉庫中的依賴包的引用,這就相當於導入了jar包。而且,maven存儲了大量的jar包和大量的依賴規則,所以你可以直接去百度搜索一下某個關鍵字+maven,就可以查找到某個框架或工具的依賴信息,直接把這個依賴信息拷貝到pom.xml中,maven就會幫你管理這個依賴。

2.maven可以幫我們進行工程管理。在以往的時候,我們開發一個項目都是在一個工程中開發,但事實上這對多人開發並不友好,多個開發者之間的開發產生了耦合關系,這對整合造成了一些小困擾(但並不是說不好,只是說有更好的手段)。而使用maven之后,可以建立多個工程來組成一個項目,在不同的工程中開發不同的模塊,而多個工程之間的關系由maven管理,maven可以幫我們把多個工程組合成一個項目。



安裝與配置:


下載:

點擊鏈接,下載Maven:

下載完了之后,直接解壓即可,它是免安裝的。


配置環境變量

  • 配置JAVA_HOME環境變量,值是jdk程序根目錄【如果已經配置過的,可以省略】

  • %JAVA_HOME%\bin添加到path環境變量中【如果已經配置過的,可以省略】【注意不要弄亂了path的值】

  • 配置MAVEN_HOME環境變量,值是maven程序根目錄

  • %MAVEN_HOME%\bin添加到path環境變量中【注意不要弄亂了path的值】

測試安裝結果:

配置了環境變量后,可以在CMD中鍵入mvn -v來測試是否可以運行,下面是我的輸出結果:

Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-18T02:33:14+08:00)
Maven home: J:\software\apache-maven-3.5.4\bin\..
Java version: 1.8.0_91, vendor: Oracle Corporation, runtime: E:\SOFTWARD\Java\jdk1.8.0_91\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

Maven概念:

在學會maven之前,先了解幾個概念。下面的概念了解即可,后面會在實際的配置中涉及。

坐標

在以往的build path過程中,其實只是把jar包的路徑引用添加到eclipse中,eclipse知道需要的包的路徑之后,在編譯的時候會去引用。

而maven可以根據坐標來指定使用哪個依賴包,坐標經過一定的組合規則就可以得出依賴包所在的路徑,maven會根據坐標對應的路徑在倉庫中來查找jar包。

  • maven用三個向量來組成一個坐標,這個坐標確定唯一的依賴包:

    • groupid:公司或組織域名倒序+項目名
    • artifactid:模塊名\工程名
    • version:jar包版本
  • maven會根據坐標在倉庫中來查找jar包,把三個向量拼接起來就是依賴包的路徑。

    • <dependency>
        		<groupId>org.springframework</groupId>
        		<artifactId>spring-core</artifactId>
        		<version>4.3.0.RELEASE</version>
        	</dependency>
      <!--對應的路徑轉換格式:groupid/artifactid/artifactid+version+.jar -->
      <!--org/springframework/spring-core/spring-core4.3.0.RELEASE  .jar-->
      

倉庫

在上面提到了坐標,你應該認識到了坐標標識了依賴包的路徑,而這個路徑是相對於倉庫的路徑的。為什么需要一個倉庫呢?上面說了eclipse實質上也是通過路徑來導入依賴包的,如果你沒有一個統一的文件夾來管理依賴包的話,零散的依賴包足以讓你頭疼了。而maven的倉庫是一個包含了眾多依賴包的倉庫,而且maven的依賴管理可以很方便地添加依賴包信息。

  • 倉庫的分類
    • 本地倉庫:本機上的倉庫,通常都會有一個本機倉庫,不然你老是需要從遠程倉庫獲取的話就很費時間了;而事實上maven會指定一個默認的本地倉庫路徑,第一次使用maven的時候,會把maven需要的插件和遠程庫中存儲的jar包下載下來並存儲到本地倉庫中。
    • 遠程倉庫:事實上你可以給本地倉庫存儲你自己的jar包,而某個jar包本地沒有的時候,就需要從遠程倉庫下載下來。
      • 私服倉庫:是一個遠程倉庫,但距離比較近,通常是企業中自己內部的maven倉庫,通常私服maven倉庫都會使用nexus來搭建。
      • 中央倉庫:是maven維護的遠程倉庫,它里面存儲的東西比較全。
  • 依賴包的查找順序:先從本地倉庫查找,本地倉庫沒有就去遠程倉庫查找(企業中一般是本地倉庫->私服倉庫->中央倉庫)。當查找到了之后,都會下載到本地倉庫。【記住初始情況下,maven的倉庫是比較干凈的,僅僅包含一些基本插件。】
  • 倉庫中存儲的內容:
    • 插件【maven的功能依賴於插件,沒有插件就沒有功能,好比電腦需要驅動,maven的構建是通過插件來實現的】
    • jar包
    • 自己開發的maven工程【其實你應該知道自己是可以把自己的工程打成jar包,然后可以在別的工程中導入這個jar包來使用這個jar包中的類,所以你是可以把自己的類庫放到倉庫中的


入門示例

下面以創建一個maven項目,並使用maven的依賴管理來給項目添加依賴為例:

創建maven工程:

關於如何創建一個maven項目,下面以eclipse中的為例,如果你需要idea的,可以點擊下面的鏈接學習。
圖解在IntelliJ IDEA中創建第一個Maven項目

新建工程->選擇maven project

添加依賴

在pom.xml中添加下列代碼:

	<dependencies>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>

可以看得出來,依賴已經導入了我們項目的類庫。

所以我們利用依賴包中的類來編寫代碼的時候就不會報錯了。


Maven標准目錄結構

maven要依據一定的目錄規范來管理項目,所以要想用maven管理項目,要遵循規范。下面會講一下目錄定義規范,這樣是面向全手動創建maven項目的時候,在很多時候,都會使用工具來創建,比如eclipse中就可以直接創建一個maven工程,這個工程遵循maven工程的目錄規范。

約定的目錄結構

maven構建一個工程要遵循這個目錄規范。

  • 工程目錄【下面的縮進程度代表目錄級數】
    • src目錄:存放工程源碼的地方
      • main目錄:存放主程序的源代碼,這里放的是主體程序代碼。
        • java目錄:存放java源文件
        • resource目錄:存放框架或其他工具的配置文件
        • 【為web項目時會多出一個webapp目錄】webapp目錄:存放頁面素材
      • test目錄:存放測試程序的源代碼的地方,這里放的都是一些測試用的代碼。
        • java目錄:存放java源文件
        • resource目錄:存放框架或其他工具的配置文件
    • pom.xml文件:這個文件定義了這個maven工程的相關配置。

補充:

  • maven使用一個pom.xml文件來管理依賴。pom中配置依賴信息和maven的一些配置信息,這會在下面講解。

pom配置:

  • pom是Project Object Model項目對象模型的意思。
  • pom.xml是maven工程的核心文件,與構建工程相關的一切配置(依賴信息、插件信息等等)都在這個文件中配置
  • pom.xml中的可配置標簽很多,我們這里僅僅介紹經常使用的。這些經常使用的也足夠你日常使用了。

常見標簽

  • modelVersion:是pom的版本,一般都是默認生成的,不需要關心
  • groupId:標識當前工程的所屬組織,寫法類似包名。【為什么工程也有這個呢?因為我們的工程也是能打包到本地倉庫的。】
  • artifactId:當前工程的工程名
  • version標簽:當前工程的版本號
  • dependencies標簽:用於管理這個工程的依賴
    • dependency標簽:指定某個依賴的信息
      • groupId:標識依賴包的所屬組織,寫法類似包名。
      • artifactId:依賴包的包名。
      • version:依賴包的版本。
      • scope標簽:依賴包的依賴范圍。

依賴級別\依賴范圍

依賴信息中的scope標簽是用來定義依賴范圍的。依賴范圍影響依賴的生存周期(就好比游戲中的特殊狀態,可能一些狀態可用於pk,一些狀態可用於打副本,一些狀態可用於任務,不同的地方影響效果是否生效。),依賴范圍的值有以下幾個:

  • compile:編譯級別的依賴會用在編譯、測試、運行的過程中。默認依賴范圍:compile
  • test:test僅僅針對test目錄下的源文件,由於test目錄下存放的是test文件,測試文件一般都不會編譯到主程序中,所以test級別的依賴是不會在編譯和運行中生效的。只在測試編譯和測試運行階段可用。這個級別的依賴包例如有junit包,junit僅僅用來測試,在主程序編譯和運行中是不需要它的。
  • provided:provided代表已提供的意思,provided范圍會用來編譯和測試,不會出現在運行中,provided主要用來處理容器也提供了我們所需要的包的情況。例如servlet-api這種依賴包tomcat容器也會提供給部署的程序,如果提供多個同名的依賴包可能會導致主程序運行出錯。
  • runtime:在編譯的時候不需要(沒有用到具體類),但是在運行和測試的時候需要用到,就可以使用這個。例如數據庫驅動包,它僅僅在運行和測試的時候會使用到這個依賴包。
  • system:類似provided,對於編譯和測試有效,運行時不需要,不建議使用,所以不講

依賴傳遞的導入

要注意,在一個工程中,如果導入的依賴需要一系列依賴(A包需要B包才能正常,那么也會導入B包),那么也會導入這一些依賴,例如struts2-core依賴一系列的包。

演示:基於eclipse

僅僅導入struts2-core的時候,maven會自動導入struts2-core所依賴的包:

發現maven自動導入了struts2-core依賴的包(這些依賴包是由struts2-core項目中的pom.xml指定的)

依賴傳遞問題

  • 依賴傳遞的過程中:
    • 路徑最短者優先
      • A依賴B,B依賴C,C依賴D(版本1.1)
      • A依賴E,E依賴D(版本1.2)
      • 導入時選擇版本D(版本1.2)
    • 路徑相同,先聲明者優先【意思是如果A同時依賴於B和C,而B和C都含有同一個依賴包P,如果在A的繼承聲明中先聲明B,那么A會繼承B的依賴包P,所以P版本取決於B】

依賴排除

可能會遇到一種情況,在同一個工程中,A包依賴B包的1.0版本,C包依賴B包的1.5版本。那么B的1.0和1.5都被引入了。這可能會導致紊亂,因為構建的時候會不清楚使用哪個版本的B依賴包。這時候我們需要使用依賴排除來解決這個問題。【一般都是排除低版本】

例如struts2-core依賴javassist包,hibernate-core也依賴javassist包,根據依賴的依賴的導入規則,這時候會有兩個javassist

為了避免紊亂,我們要使用exclusions排除。在eclipse中,我們可以在Dependency Hierarchy中右鍵選中包進行排除,也可以使用以下xml式排除:

  	<dependency>
  		<groupId>org.apache.struts</groupId>
  		<artifactId>struts2-core</artifactId>
  		<version>2.3.34</version>
  		<exclusions>
            <!-- 排除struts2-core的依賴中的javassist依賴 -->
  			<exclusion>
  				<groupId>javassist</groupId>
  				<artifactId>javassist</artifactId>
  			</exclusion>
  		</exclusions>
  	</dependency>

依賴的繼承

在建立多個有繼承關系的工程時,父工程的依賴信息會傳遞給子工程。
在父工程中聲明了依賴后,就算子工程沒有聲明,也會傳遞到子工程中

版本鎖定

在分模塊開發時,多個子模塊可能會使用上同一個依賴包,那么如何限定多個子模塊都使用同一版本的依賴包呢?可以使用版本鎖定。

  • 在父工程使用dependencyManagement來管理依賴(dependencyManagement不會導入依賴),那么依賴的版本會被父工程鎖定。
  • 通常情況下,父工程的依賴會傳遞給子工程(如果你另外也使用了dependencies標簽來聲明依賴),那么子工程不聲明的時候是沒問題的;如果子工程顯式導入被鎖定版本的依賴時,會報錯,會提示版本被父工程鎖定。
<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>junit</groupId>
				<artifactId>junit</artifactId>
				<version>4.9</version>
				<scope>test</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

統一管理依賴版本:

你應該經常見到某個框架的依賴包都是同一版本的,如果我們將這些依賴信息都添加到pom.xml中,可能會出現多個重復的version標簽,如果你要修改的話是很麻煩的,要逐個逐個去修改版本。

事實上,是可以統一管理依賴版本的,同一管理依賴版本之后,如果我們要修改這個框架下的包的版本,那么只需要修改一處就行了。

  • 使用properties內使用自定義標簽統一版本號,自定義標簽相當於一個變量,后面的version那里可以引用這個變量。
 <properties>
     <!-- 使用自定義標簽統一版本號,標簽名是自定義的 -->
  	<struts2-version>2.3.34</struts2-version>
  </properties>
  
  <dependencies>
  	<dependency>
  		<groupId>org.apache.struts</groupId>
  		<artifactId>struts2-core</artifactId>
        <!--在version標簽中引用 -->
  		<version>${struts2-version}</version>
  	</dependency>
  </dependencies>

注意:properties標簽並不是只能用於統一聲明依賴版本,但凡是需要統一聲明的地方都可以考慮使用properties標簽。



Maven命令

全局命令

  • maven -v :查看版本

工程級命令

以下命令針對於maven工程,必須到pom.xml目錄才能執行命令

  • mvn clean:清理之前編譯出的class文件,相當於清理target目錄及其目錄下的所有文件。
  • mvn compile:編譯主程序,效果是把src/main/java下的java源文件編譯為class文件並輸出到target下的classes目錄下。
  • mvn test-compile:編譯測試程序
  • mvn test:執行src/test/java下的單元測試類,會打印出測試結果(如果被junit標識成測試類的話),並把src/main/java下的java源文件編譯為class文件並輸出到target下的test-classes目錄下。
  • mvn package:打包,java項目打包成jar包,web項目打包成war包。打包的文件存儲到target目錄下。
  • mvn install:安裝,把maven工程打包成jar包或war包並保存到本地倉庫中。【在本地倉庫目錄下根據坐標來生成包路徑來保存】。對於我們自己的maven工程,可以使用mvn install把它安裝到倉庫中。

命令生命周期

  • 屬於同一個生命周期的指令,當后面的命令執行時,前面的命令也會自動執行。
  • 常見命令周期:
    • clean :在進行真正構建之前的一些清理工作。
      • 包含命令:pre-clean,clean,post-clean
    • default:構建的核心部分:編譯、測試、打包、部署等等。【要注意,大部分命令都處於default生命周期,所以執行某個命令時,生命周期前面的命令也會自動執行。】
      • 包含命令:validate,compile,test,package,verify,install,deploy....
    • site:生成項目報告、站點、發布站點。。
      • 包含命令:pre-site,site,post-site,site-deploy

每一個階段都有一個對應的命令,且有相應的插件來支持命令的運行。


setting.xml配置文件

倉庫配置

本地倉庫配置

maven安裝路徑下\conf\settings.xml文件,在settings.xml中配置localResposity標簽。,它是被注釋了的,有配置方法的提示。

默認目錄:用戶目錄下.m2/repository

添加遠程倉庫

<mirrors>
	<!-- 中央倉庫1 -->
        <mirror>
            <id>repo1</id>
            <mirrorOf>central</mirrorOf>
            <name>Human Readable Name for this Mirror.</name>
            <url>http://repo1.maven.org/maven2/</url>
        </mirror>

        <!-- 中央倉庫2 -->
        <mirror>
            <id>repo2</id>
            <mirrorOf>central</mirrorOf>
            <name>Human Readable Name for this Mirror.</name>
            <url>http://repo2.maven.org/maven2/</url>
        </mirror>
</mirrors>
        

Eclipse中使用maven

配置maven

eclipse有自帶的maven插件,但不建議使用。

把獨立的maven添加成一個新的maven:

配置user settings:

創建maven工程:

【maven model用於分模塊開發時創建子工程,多個子工程與核心工程組成一個完整的項目。】

新建工程->選擇maven project

下面給的是打包方式為war的時候的目錄結構:

修改JRE版本:

默認情況下,maven工程引用的jre庫是1.5的,這可能會導致一些語法問題(例如泛型的語法問題),所以通常需要更改這個引用的jre庫版本。

  • 修改方法:在setting.xml中修改profiles標簽
<profile>
			<id>jdk18</id>
			<activation>
				<activeByDefault>true</activeByDefault>
				<jdk>1.8</jdk>
			</activation>
			<properties> 
				<maven.compiler.source>1.8</maven.compiler.source>  
				<maven.compiler.target>1.8</maven.compiler.target>  
				<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
				<maven.compiler.encoding>utf-8</maven.compiler.encoding>
			</properties>
</profile>

導入依賴

  • 方式一:手動添加,通過手動拷貝等方式統一增加。可以百度包名+maven來查找依賴信息的寫法,拷貝下來粘貼到pom.xml中即可。

    • <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.1.0</version>
          <scope>provided</scope>
      </dependency>
      
  • 方式二:在eclipse,雙擊打開pom.xml,默認情況下不是xml界面,點擊下面的dependencies選項,再點擊add,在中間的搜索框輸入信息搜索依賴,選擇依賴包,最后點擊確認。這要求你比較熟悉需要哪些包。

1539015718240

1539015941160

添加插件

有時候我們希望給maven工程添加額外的插件,例如tomcat7:run插件,這個插件能使得我們的工程虛擬地部署到tomcat中。

  • mvn tomcat:run 命令是一個插件,需要添加才能執行這條命令,添加方式:項目右鍵選擇maven,再add plugin,然后搜索tomcat

    • <!--build與dependencies是同一級的 -->
      <build>
        	<plugins>
        		<plugin>
        			<groupId>org.apache.tomcat.maven</groupId>
        			<artifactId>tomcat7-maven-plugin</artifactId>
        			<version>2.2</version>
        		</plugin>
              <configuration>
      		<!-- 端口 -->
      		<port>8080</port>
      		<!-- 訪問路徑 -->
      		<path>/helloworld</path>
      		<!-- 編碼 -->
      		<uriEncoding>utf-8</uriEncoding>
      	</configuration>
        	</plugins>
      </build>
      

這里僅僅給一個添加插件的示例,其他的插件有興趣可以自查。

Eclipse中執行maven命令

工程右鍵->run as ->第一個maven build可以讓你選擇之前執行過的命令來執行,第二個maven build可以讓你輸入指定命令來執行(在goals中輸入命令,mvn test只需要輸入test即可);至於后面的clean,install和test的意思已經顯而易見了。

創建web工程

如果想創建一個web工程,需要在創建工程的時候打包方式改成war。但默認情況下src/main下是沒有webapp目錄(存放WEB-INF目錄和web.xml的目錄)的。

  • 生成webapp目錄:
    • 方式一: WEB-INF目錄和web.xml,javaEE tools->Generate Deploy...
    • 方式二:手動創建目錄和文件

依賴范圍沖突問題:

什么是依賴范圍沖突呢?這涉及到依賴范圍問題,主要是provided問題。以servlet-api依賴為例,這個依賴tomcat會提供給我們部署的項目,但如果我們添加這個依賴的時候選擇了compile,那么這個依賴也會帶到部署的項目中,使得存在了兩個servlet-api依賴。

解決方法:這時候要修改servlet-api依賴的范圍,改成provided。

依賴排除問題:

這個在pom配置的依賴排除中講過了。這里只提一下,不再演示。

如何運行項目

java項目:

  • 運行方式一:項目右鍵->run as->java application
  • 由於方式二跟直接到目標目錄執行java沒什么區別,所以這里不講,有興趣可以自查mvn exec

web項目:

  • 部署方式一:在添加了插件之后,使用tomcat插件部署:mvn tomcat7:run
    • 選擇5 Maven build之后,輸入命令tomcat7:run
    • 區別:插件的是虛擬環境,會比較快。
  • 部署方式二:打成war包之后,把war包拷貝到tomcat目錄中。
  • 部署方式三:建立服務器之后,把項目添加到tomcat中;或者在pom.xml文件點擊右鍵,直接把項目添加到tomcat中。

工程拆分和聚合

  • 在一個比較大的項目開發協作中,如果按照以前的開發的話,是一個工程。這樣會有一些問題。拆分、分模塊便於測試和開發。不同開發者僅僅面向自己的工程。
  • 然后在整合的時候,把工程聚合起來,就能聚合成一個完整的項目了。

工程的拆分

工程的拆分是創建一個核心父工程,然后創建多個子模塊的情況。核心父工程一般不會編寫什么內容,一般只作為依賴的匯總(讓父工程引入共有依賴,子工程單獨依賴的單獨引入)。

創建父工程:

創建子工程

為了讓父工程能管理到子工程,所以在父工程下右鍵"new-->maven module"

創建完父工程和子模塊后,可以在父工程的pom.xml中看到父工程管理到了子模塊:

而子模塊也指向了父工程:

然后子模塊怎么開發呢?它相當於與一個獨立的模塊,所以你可以像往常一樣開發。不過提一下的是,可能會發生service層調用dao層,那么這怎么實現呢?這就需要我們在service層中添加dao層的依賴了,這樣service層就可以調用dao層的方法了。

這里提一下工程拆分與框架整合的問題,在以前一個工程中,dao和service都是交給spring去管理的,那么現在
該怎么處理呢?首先,要注意的是,只要我們配置了spring(這里注意,依賴已經導入了),無論是xml還是注解
式,那么spring就能夠管理好我們的bean。所以,我們現在其實只需要關心我們的bean是否交給了spring來管理
即可。而這個單個模塊的測試可以在test目錄下再編寫代碼來測試。

工程的聚合

拆分工程之后,開發完成了,怎么聚合使用呢?
首先,要注意父工程管理着子模塊,

如果打包父工程,那么子工程也會進行打包。

而通常我們在進行web開發的時候,由於子模塊web是核心項目,而子模塊web又依賴着子模塊service,而在打包的時候依賴的包也會打成jar包,所以打包子模塊web的時候,web工程的lib里面是有依賴的兄弟工程的,所以我們可以直接運行web工程即可。【這是運行war包的情況】

我們也可以選擇在IDE中直接運行子模塊web(在eclipse直接run as),也是能夠調用到其他兄弟模塊的功能的。


寫在最后

這篇關於maven的博文看完了,你應該能對maven的使用有一個基本的了解。

這里給一個常用的查maven的依賴信息的網站:mvnrepository.com



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM