1. 程式人生 > >自動化構建工具:Maven

自動化構建工具:Maven

1.目前掌握的技術


2.目前的技術在開發中存在的問題(Why)

    ①一個專案就是一個工程

(如果專案非常龐大,就不適合繼續使用package來劃分模組,最好是每個模組對應一個人工程,利於分工協作)

    ②專案中需要的jar包必須手動“複製”、“貼上”到WEB-INF/lib目錄下

(帶來的問題是:同樣的jar包檔案重複出現在不同的專案工程中,一方面浪費儲存空間,另一方面也讓工程比較臃腫)

    ③jar包需要別人替我們準備好,或到官網進行下載

(不同技術的官網提供jar包下載的形式五花八門的,有些技術的官網就是通過Maven或SVN等專門的工具提供下載的。

如果是以不規範的方式下載的jar包,那麼其中的內容很可能也是不規範的。

藉助於Maven可以以一種規範的方式下載jar包,因為所有知名框架或第三方工具的jar包以及按照統一的規範存放在了Maven的中央倉庫中,以規範的方式下載的jar包,內容也是可靠的。

Tips:"統一的規範",不僅是對IT開發領域非常重要,對於整個人類社會都是非常重要的。)

    ④一個jar包依賴其他jar包需要自己手動加入到專案中

(FileUpload元件-->IO元件。commons-fileupload-1.3jar依賴於commons-io-2.0.1jar。

如果所有jar包之間的依賴關係 都需要程式設計師自己非常的瞭解,那麼就會極大的增加學習成本。

Maven會自動將被依賴的jar包匯入進來。)

3.Maven是什麼(What)

    ①Maven是一款服務於Java平臺的自動化構建工具。

            Make-->Ant-->Maven-->Gradle

    ②構建

            [1]概念:以“Java原始檔”、“框架配置檔案”、“JSP”、“HTML”、“圖片”等資源為“ 原材料”,

            去“生產”一個可以執行的專案的過程。

                編譯、部署、搭建

              [2]編譯:Java原始檔[User.java]-->編譯-->Class位元組碼檔案[User.class]-->交給JVM去執行

              [3]部署:一個BS專案最終執行的並不是動態Web工程本身,而是這個動態Web工程“編譯的結果”

                            生成的雞-->處理-->熟的雞

                            動態Web工程-->編譯、部署-->編譯結果

                              

                        開發過程中,所有的路徑或配置檔案中配置的類路徑等都是以編譯結果的目錄結構為標準的。

                Tips:執行時環境

                        

                        其實是一組jar包的引用,並沒有把jar包本身複製到工程中,所以並不是目錄。

                Tips:tc_server

                        整個目錄複製到eclipse解壓安裝目錄下的dropins目錄下即可

                        

                    或是自己從官方下載,轉載一篇部落格教程地址http://blog.csdn.net/a332056918/article/details/76180530

    ③構建過程中的各個環節

            [1]清理:將以前編譯得到的舊的class位元組碼檔案刪除,為下一次編譯做準備

            [2]編譯:將Java源程式編譯成class位元組碼檔案

            [3]測試:自動測試,自動呼叫junit程式

            [4]報告:測試程式執行的結果

            [5]打包:動態Web工程打war包,Java工程打jar包

            [6]安裝:Maven特定的概念----將打包得到的檔案複製到“倉庫”中的指定位置

            [7]部署:將動態Web工程生成的war包複製到Servlet容器的指定目錄下,使其可以執行

    ④自動化構建

4.安裝Maven核心程式

    ①檢查JAVA_HOME環境變數

    

    ②解壓Maven核心程式的壓縮包,放在一個非中文無空格路徑下

    E:\maven\apache-maven-3.5.2

    ③配置Maven相關的環境變數

        [1]MAVEN_HOME或M2_HOME

            

         [2]Path

            

    ④驗證:執行mvn -v命令檢視Maven版本

        

5.Maven的核心概念

    ①約定的目錄結構

    ②POM

    ③座標

    ④依賴

    ⑤倉庫

    ⑥生命週期/外掛/目標

    ⑦繼承

    ⑧聚合

6.第一個Maven工程

①建立約定的目錄結構

        [1]根目錄:工程名

        [2]src目錄:原始碼

        [3]pom.xml檔案:Maven工程的核心配置檔案

        [4]main目錄:存放主程式

        [5]test目錄:存放測試程式

        [6]java目錄:存放Java原始檔

        [7]resources目錄:存放框架或其他工具的配置檔案

②為什麼要遵守約定的目錄結構呢?

    Maven要負責我們這個專案的自動化構建,以編譯為例,Maven要想自動進行編譯,那麼它必須知道Java原始檔儲存在哪裡。

    如果我們自己自定義的東西想讓框架或工具知道,有兩種辦法

           --以配置檔案的方式明確告訴框架

                

           --遵守框架內部已存在的約定

                log4j.properties

                log4j.xml

                       約定>配置>編碼

目錄結構   

Hello

|---src
|---|---main
|---|---|---java
|---|---|---resources
|---|---test
|---|---|---java
|---|---|---resources

|---pom.xml

POM檔案內容

<?xml version="1.0" ?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.atguigu.maven</groupId>
	<artifactId>Hello</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<name>Hello</name>
	  
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.0</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

編寫主程式程式碼

        在src/main/java/com/atguigu/maven目錄下新建檔案Hello.java,內容如下

package com.atguigu.maven;
		public class Hello {
			public String sayHello(String name){
				return "Hello "+name+"!";
			}
		}

編寫測試程式碼

        在/src/test/java/com/atguigu/maven目錄下新建測試檔案HelloTest.java

package com.atguigu.maven;	
		import org.junit.Test;
		import static junit.framework.Assert.*;
		public class HelloTest {
			@Test
			public void testHello(){
				Hello hello = new Hello();
				String results = hello.sayHello("litingwei");
				assertEquals("Hello litingwei!",results);	
			}
		}

執行幾個基本的Maven命令

                mvn compile編譯
mvn clean清理
mvn test測試
mvn package打包
※注意:執行Maven命令時一定要進入pom.xml檔案所在的目錄!

7.常用Maven命令

    ①注意:執行與構建過程相關的Maven命令,必須進入pom.xml所在的目錄。

            與構建過程相關:編譯、測試、打包、.......

    ②常用命令

        [1]mvn clean : 清理

         [2]mvn compile : 編譯主程式

         [3]mvn test-compile : 編譯測試程式

         [4]mvn test : 執行測試

         [5]mvn package : 打包

         [6]mvn site : 生成站點

8.關於聯網問題

        ①Maven的核心程式中僅僅定義了抽象的生命週期,但是具體的工作必須由特定的外掛來完成。

而外掛本身並不包含在Maven的核心程式中。

        ②當我們執行的Maven命令需要用到某些外掛時,Maven核心程式會首先到本地倉庫中查詢。

        ③本地倉庫的預設位置:[系統中當前使用者的家目錄]\.m2\repository

            C:\Users\ 登入當前系統的使用者名稱\.m2\repository

        ④Maven核心程式如果在本地倉庫中找不到需要的外掛,那麼它會自動連線外網,到中央倉庫中下載。

        ⑤如果此時無法連線外網,則構建失敗。

        ⑥修改預設本地倉庫的位置可以讓Maven核心程式到我們事先準備好的目錄下查詢外掛

                [1]找到Maven解壓目錄\conf\settings.xml

                [2]在settings.xml檔案中找到localRepository標籤

                [3]將<localRepository>/path/to/localrepo</localRepository>從註釋中取出

                [4]將標籤體內容修改為已準備好的Maven倉庫目錄

                <localRepository>D:\RepMaven</localRepository>

9.POM

    ①含義:Project Object Model 專案物件模型

            DOM Document Object Model 文件物件模型

    ②pom.xml對於Maven工程是核心配置檔案,與構建過程相關的一切設定都在這個檔案中進行配置。

            重要程度相對於web.xml對於動態Web工程

10.座標

    ①數學中的座標:

        [1]在平面上,使用X、Y兩個向量可以唯一的定位平面中的任何一個點。

        [2]在空間中,使用X、Y、Z三個向量可以唯一的定位空間中的任何一個點。

    ②Maven的座標

        使用下面三個向量在倉庫中唯一定位一個Maven工程

        [1]groupid:公司或組織域名倒序+專案名

        <groupid>com.atguigu.maven</groupid>

        [2]artifactid:模組名

        <artifactid>Hello</artifactid>

        [3]version:版本

        <version>1.0.0</version>

        ③座標與倉庫中路徑的對應關係

                <groupId>org.springframework</groupId>
              <artifactId>spring-core</artifactId>
              <version>4.0.0.RELEASE</version>

        org/springframework/spring-core/4.0.0.RELEASE/spring-core-4.0.0.RELEASE.jar

11.倉庫

①倉庫的分類

            [1]本地倉庫:當前電腦上部署的倉庫目錄,為當前電腦上所有Maven工程服務

            [2]遠端倉庫

                    (1)私服:搭建在區域網環境中,為區域網範圍內的所有Maven工程服務

                        

                    (2)中央倉庫:架設在Internet上,為全世界所有Maven工程服務

                    (3)中央倉庫映象:為了分擔中央倉庫的流量,提升使用者訪問速度

②倉庫中儲存的內容:Maven工程

        [1]Maven自身所需要的外掛

        [2]第三方框架或工具的jar包

        [3]我們自己開發的Maven工程

第二個Maven工程

<?xml version="1.0" ?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.atguigu.maven</groupId>
	<artifactId>HelloFriend</artifactId>
	<version>0.0.1-SNAPSHOT</version><!--SNAPSHOT為快照版的,作為開發時版本使用;RELEASE為正式版-->
	<name>HelloFriend</name>
	
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.0</version>
			<scope>test</scope>
		</dependency>		
		
		<dependency>
			<groupId>com.atguigu.maven</groupId>
			<artifactId>Hello</artifactId>
			<version>0.0.1-SNAPSHOT</version>
			<scope>compile</scope>
		</dependency>
		
	</dependencies>
</project>
主程式:在src/main/java/com/atguigu/maven目錄下新建檔案HelloFriend.java
package com.atguigu.maven;	
		import com.atguigu.maven.Hello;
		public class HelloFriend {
			public String sayHelloToFriend(String name){
				Hello hello = new Hello();
				String str = hello.sayHello(name)+" I am "+this.getMyName();
				System.out.println(str);
				return str;
			}
			public String getMyName(){
				return "John";
			}
		}

測試程式:在/src/test/java/com/atguigu/maven目錄下新建測試檔案HelloFriendTest.java

package com.atguigu.maven;	
		import static junit.framework.Assert.assertEquals;
		import org.junit.Test;
		import com.atguigu.maven.Hello;
		
		public class HelloFriendTest {
			@Test
			public void testHelloFriend(){
				HelloFriend helloFriend = new HelloFriend();
				String results = helloFriend.sayHelloToFriend("litingwei");
				assertEquals("Hello litingwei! I am John",results);	
			}
		}

執行Maven命令

mvn install安裝

12.依賴(初步)

①Maven解析依賴資訊時會到本地倉庫中查詢被依賴得到jar包。

        對於我們自己開發的Maven工程,使用install命令安裝後就可以進入倉庫。

    ②依賴的範圍

        

        [1]compile

                對主程式是否有效:有效

                對測序是否有效:有效

                是否參與打包:參與

                是否參與部署:參與

                典型例子:spring-core

        [2]test範圍依賴

                    對主程式是否有效:無效

                    對測試範圍是否有效:有效

                    是否參與打包:不參與

                    是否參與部署:不參與

                    典型例子:junit

          [3]provided範圍依賴

                對主程式是否有效:有效

                對測試程式是否有效:有效            

                是否參與打包:不參與

                是否參與部署:不參與

                典型例子:servlet-api.jar

                

13.生命週期

        ①各個構建環節執行的順序:不能打亂順序,必須按照既定的正確順序來執行。

        ②Maven的核心程式中定義了抽象的生命週期,生命週期中各個階段的具體任務是由外掛來完成的。

        ③Maven核心程式為了更好的實現自動化構建,按照這一特點執行生命週期的各個階段:無論現在要執行生命週期中的哪一個階段,都是從這個生命週期最初的位置開始執行。

mvn compile


mvn test


mvn package


    ④外掛和目標

            [1]生命週期的各個階段僅僅定義了要執行的任務是什麼。

            [2]各個階段和外掛的目標是相對應的。

            [3]相似的目標由特定的外掛來完成。


            [4]可以將目標看作“呼叫外掛功能的命令”

14.在Eclipse中使用Maven

    ①Maven外掛:Eclipse內建

            [1]installations:指定Maven核心程式的位置。不建議使用外掛自帶的Maven程式,而應該使用我們自己解壓的那個。

           

  [2]user settings:指定conf/settings.xml的位置,進而獲取本地倉庫的位置。


    global settings 本機器的配置,使用這臺機器的所有使用者都是用這個配置

    user settings    當前使用者的配置

       * 個人配置會覆蓋全域性配置

    通過user settings中settings.xml位置,進而知道本地倉庫的位置(Local Repository)

            *注意:新的工作空間需要重新設定

    ②基本操作

            [1]建立Maven版的Java工程





跳過skup archetype selection這種方式(建立後目錄不全,不建議使用),使用簡單的方式來建立



建立好發現每次都要更改jdk版本


第三個Maven工程

①設定通過Maven建立的工程的JDK版本——一勞永逸
[1]開啟settings.xml檔案
[2]找到profiles標籤

[3]加入如下配置

<profile>
				<id>jdk-1.7</id>
				<activation>
					<activeByDefault>true</activeByDefault>
					<jdk>1.7</jdk>
				</activation>
				<properties>
					<maven.compiler.source>1.7</maven.compiler.source>
					<maven.compiler.target>1.7</maven.compiler.target>
					<maven.compiler.compilerVersion>1.7</maven.compiler.compilerVersion>
				</properties>
</profile>

另外在標籤<mirrors>中,更改標籤中對應程式碼如下,從阿里雲倉庫中下載,可以使下載的外掛速度加快

	<mirror>
           <id>nexus-aliyun</id>
           <mirrorOf>*</mirrorOf>
           <name>Nexus aliyun</name>
           <url>http://maven.aliyun.com/nexus/content/groups/public</url>
	</mirror>

②工程座標

groupId:com.atguigu.maven
ArtifactId:MakeFriends
Package:com.atguigu.maven

③在src/main/java中新建類com.atguigu.maven.MakeFriends

public String makeFriends(String name){
			HelloFriend friend = new HelloFriend();
			friend.sayHelloToFriend("litingwei");
			String str = "Hey,"+friend.getMyName()+" make a friend please.";
			System.out.println(str);
			return str;
		}

④在src/test/java中新建類com.atguigu.maven.MakeFriendsTest

package com.atguigu.maven;
		import static junit.framework.Assert.assertEquals;
		import org.junit.Test;
		public class MakeFriendsTest {
			@Test
			public void testMakeFriends(){		
				MakeFriends makeFriend = new MakeFriends();
				String str = makeFriend.makeFriends("litingwei");
				assertEquals("Hey,John make a friend please.",str);
			}
		}

⑤新增依賴資訊

<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.9</version>
			<scope>test</scope>
		</dependency>
		<dependency>
	    	<groupId>com.atguigu.maven</groupId>
	    	<artifactId>HelloFriend</artifactId>
	    	<version>0.0.1-SNAPSHOT</version>
	    	<type>jar</type>
	    	<scope>compile</scope>
		</dependency>

⑥在Eclipse環境下執行Maven命令:右擊pom.xml選擇run as 中的命令執行即可



        [2]建立Maven版的Web工程





建立jsp頁面報錯

-->The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path

解決方法

在pom.xml中新增ServletAPI依賴

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

jsp中EL表示式程式碼提示,在pom.xml中新增JSPAPI依賴

<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1.3-b06</version>
			<scope>provided</scope>
</dependency>

jar包之間的衝突



與Tomcat的包衝突,<scope>裡應改為原來預設的provided

匯入手動建立的Maven工程


根據pom.xml識別工程


生成Eclipse能識別的檔案


*用Maven方式匯入不能複製工程到工作區

*平時的開發不必將引入別的模組安裝到倉庫中,在開發完成後,直接打包就會自動構建執行一系列命令,在Eclipse中的開發沒有將引入的模組安裝到倉庫中也是可以用的。

15.依賴(高階)

    ①依賴的傳遞性


        [1]好處:可以傳遞的依賴不必在每個模組工程中都重複宣告,在“最下面”的工程中依賴一次即可。

        [2]注意:非compile範圍的依賴不能傳遞。所以在各個工程模組中,如果有需要就得重複宣告依賴。

    ②依賴的排除

        [1]需要設定依賴排除的場合

            

        [2]依賴排除的設定方式在pom.xml依賴的模組<scope>標籤後加入

            

    ③依賴的原則

            [1]作用:解決j模組工程之間的jar包衝突問題  

            [2]情景設定1:驗證路徑最短者優先原則

                  

            [3]情景設定2:驗證路徑相同時先宣告者優先

                    

    ④統一管理依賴的版本

        [1]情景舉例

            

            這裡對Spring各個jar包依賴的版本都是4.0.0

            如果需要統一升級為4.1.1,怎麼辦?手動逐一修改不可靠。

       [2]建議配置方式

                i.使用properties標籤內使用自定義標籤統一宣告版本號

                

                ii.在需要統一版本的位置,使用${自定義標籤名}引用宣告的版本號

                

               [3]其實properties標籤配合自定義標籤宣告資料的配置並不是只能用於宣告依賴的版本號。凡是需要統一聲明後再引用的場合都可以使用。

                

16.繼承

①現狀

        Hello依賴的junit:4.0

        HelloFriend依賴的junit:4.0

        MakeFriends依賴的junit:4.9

        由於test範圍的依賴不能傳遞,所以必然會分散在各個模組工程中,很容易造成版本不一致。

②需求:統一管理各個模組工程中對juniit依賴的版本

③解決思路:將junit依賴統一提取到“父”工程中,在子工程中宣告junit依賴時不指定版本,以父工程中統一設定的為準。同時也便於修改。

④操作步驟

        [1]建立一個Maven工程作為父工程。注意打包的方式pom


        [2]在子工程中宣告對父工程的引用


    [3]將子工程的座標中與父工程座標中重複的內容刪除


    [4]在父工程中統一管理junit的依賴


    [5]在子工程中刪除junit依賴的版本號部分

        

    ⑤注意:配置繼承後,執行安裝命令時要先安裝父工程。

17.聚合

①作用:一鍵安裝各個模組工程。

    ②配置方式:在一個“總的聚合工程”中配置各個參與聚合的模組


    ③使用方式:在聚合工程的pom.xml上點右鍵run as-->maven install

18.Web工程自動部署

<!--配置當前工程構建過程中的特殊設定-->
<build>
		<finalName>AtguiguWeb</finalName><!--最終的名字-->
		<plugins><!--配置構建過程需要使用的外掛-->
			<plugin><!--cargo是一家專門從“啟動Servlet容器”的組織-->
				<groupId>org.codehaus.cargo</groupId>
				<artifactId>cargo-maven2-plugin</artifactId>
				<version>1.2.3</version>
				<configuration><!--配置當前系統中容器的位置-->
					<container>
						<containerId>tomcat6x</containerId>
						<home>D:\DevInstall\apache-tomcat-6.0.39</home>
					</container>
					<configuration>
						<type>existing</type>
						<home>D:\DevInstall\apache-tomcat-6.0.39</home>
						<!-- 如果Tomcat埠為預設值8080則不必設定該屬性 -->
						<properties>
							<cargo.servlet.port>8989</cargo.servlet.port>
						</properties>
					</configuration>
				</configuration>
				<executions>  <!--配置外掛在什麼情況下執行-->
					<execution>  
						<id>cargo-run</id>  
						<phase>install</phase>  <!--生命週期的階段-->
						<goals>  
							<goal>run</goal> <!--外掛的目標--> 
						</goals>  
					</execution>  
				</executions>
			</plugin>
		</plugins>
	</build>

需在命令列中啟動,在Eclipse啟動可以,但不能停止


ctrl+c關閉

Maven官方網址:http://mvnrepository.com,尋找相關依賴