沉淀,再出發:Maven的使用和規范
一、前言
Maven作為項目管理工具,在一個大型項目開發的每個階段都有着很大的用處,為什么需要這個東西呢,還是為了消除不確定性,統一化管理,正如我們做的每一件事其實都是為了消除不確定性一樣,知道的越多不確定性就越少,在程序開發之中大家分工協作,每個人可能使用不同的插件、包以及其他工具,這些東西大多是從網上下載的,要知道軟件都是有版本的,有的功能可能在這個版本沒有,下個版本卻有了,那么如果大家雖然都使用同一個軟件,但是用的是不一樣的版本的,在項目后期的合並之中造成的麻煩是非常嚴重的,要怎么辦呢?!當然我們可以提前定義好要使用的工具以及版本號,可是還是有人會忘記或者搞錯,只要一個人的錯了,那么上傳到Github等項目托管平台上,其他人pull下來的時候就糟糕了,會因為相互混合而導致項目運行失敗,這樣的責任誰去負責呢?!於是Maven這個神器就應用而生了,它的出現就是為了統一風格、統一使用的工具、統一一切可以規范的。這種統一對於我們的項目意義深遠,更加了不起的是,它能夠從本地倉庫和中央倉庫之中將這些統一標准的軟件自動下載下來,這就極大的將程序員從各種復雜的環境配置中解放了出來,可以直接將精力和時間放到業務需求以及代碼的開發上,因此,程序員如果不懂得Maven、Github這類項目管理工具應該說不能算是程序員,只能算是初學者或者打醬油的。
那么在信息爆炸的時代,到底需要學習maven的哪些知識呢?要學到什么程度?本文我們就來探討一下。
二、從基礎開始
首先我們需要安裝被配置java的環境,之后才能使用maven。
2.1、下載
最基礎的就是安裝了,我們以windows為例來說明,首先從官網上下載Maven這個軟件。養成好的習慣,下載最新的、最穩定的或者最適合的版本,並且使用SHA1算法驗證一下下載的是不是正確的,可以看到驗證成功。
2.2、安裝配置
接下來就是安裝和配置了,maven比較簡單,不用向注冊表中寫入內容就可以,直接解壓到一個目錄下就等於安裝了,此時就可以使用了,但是每一次都要切換到這個目錄下的.\bin目錄非常的麻煩,因此有必要配置一下環境變量,將該目錄寫入到PATH環境變量中去,至於有的上面再加一個變量名叫做M2_HOME=“Maven文件目錄”的也是為了規范化,理解了本質的我們是不用這樣做的,直接增加就可以。一定要是bin目錄,然后才能使用這個文件夾下的軟件功能。
在這里我們找到了經常使用的工具mvn,打開可以看到里面的代碼正是為了我們輸入的命令服務的。
mvn代碼:

#!/bin/sh # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # ----------------------------------------------------------------------------- # Apache Maven Startup Script # # Environment Variable Prerequisites # # JAVA_HOME Must point at your Java Development Kit installation. # MAVEN_OPTS (Optional) Java runtime options used when Maven is executed. # MAVEN_SKIP_RC (Optional) Flag to disable loading of mavenrc files. # ----------------------------------------------------------------------------- if [ -z "$MAVEN_SKIP_RC" ] ; then if [ -f /etc/mavenrc ] ; then . /etc/mavenrc fi if [ -f "$HOME/.mavenrc" ] ; then . "$HOME/.mavenrc" fi fi # OS specific support. $var _must_ be set to either true or false. cygwin=false; mingw=false; case "`uname`" in CYGWIN*) cygwin=true;; MINGW*) mingw=true;; esac ## resolve links - $0 may be a link to Maven's home PRG="$0" # need this for relative symlinks while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG="`dirname "$PRG"`/$link" fi done saveddir=`pwd` MAVEN_HOME=`dirname "$PRG"`/.. # make it fully qualified MAVEN_HOME=`cd "$MAVEN_HOME" && pwd` cd "$saveddir" # For Cygwin, ensure paths are in Unix format before anything is touched if $cygwin ; then [ -n "$MAVEN_HOME" ] && MAVEN_HOME=`cygpath --unix "$MAVEN_HOME"` [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"` fi # For MinGW, ensure paths are in Unix format before anything is touched if $mingw ; then [ -n "$MAVEN_HOME" ] && MAVEN_HOME=`(cd "$MAVEN_HOME"; pwd)` [ -n "$JAVA_HOME" ] && JAVA_HOME=`(cd "$JAVA_HOME"; pwd)` # TODO classpath? fi if [ -z "$JAVA_HOME" ] ; then JAVACMD=`which java` else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then echo "The JAVA_HOME environment variable is not defined correctly" >&2 echo "This environment variable is needed to run this program" >&2 echo "NB: JAVA_HOME should point to a JDK not a JRE" >&2 exit 1 fi CLASSWORLDS_JAR=`echo "${MAVEN_HOME}"/boot/plexus-classworlds-*.jar` CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher # For Cygwin, switch paths to Windows format before running java if $cygwin ; then [ -n "$MAVEN_HOME" ] && MAVEN_HOME=`cygpath --path --windows "$MAVEN_HOME"` [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --windows "$CLASSPATH"` [ -n "$CLASSWORLDS_JAR" ] && CLASSWORLDS_JAR=`cygpath --path --windows "$CLASSWORLDS_JAR"` fi # traverses directory structure from process work directory to filesystem root # first directory with .mvn subdirectory is considered project base directory find_maven_basedir() { ( basedir=`find_file_argument_basedir "$@"` wdir="${basedir}" while [ "$wdir" != '/' ] ; do if [ -d "$wdir"/.mvn ] ; then basedir=$wdir break fi wdir=`cd "$wdir/.."; pwd` done echo "${basedir}" ) } find_file_argument_basedir() { ( basedir=`pwd` found_file_switch=0 for arg in "$@"; do if [ ${found_file_switch} -eq 1 ]; then if [ -d "${arg}" ]; then basedir=`cd "${arg}" && pwd -P` elif [ -f "${arg}" ]; then basedir=`dirname "${arg}"` basedir=`cd "${basedir}" && pwd -P` if [ ! -d "${basedir}" ]; then echo "Directory ${basedir} extracted from the -f/--file command-line argument ${arg} does not exist" >&2 exit 1 fi else echo "POM file ${arg} specified with the -f/--file command line argument does not exist" >&2 exit 1 fi break fi if [ "$arg" = "-f" -o "$arg" = "--file" ]; then found_file_switch=1 fi done echo "${basedir}" ) } # concatenates all lines of a file concat_lines() { if [ -f "$1" ]; then echo "`tr -s '\r\n' ' ' < "$1"`" fi } MAVEN_PROJECTBASEDIR="${MAVEN_BASEDIR:-`find_maven_basedir "$@"`}" MAVEN_OPTS="`concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config"` $MAVEN_OPTS" # For Cygwin, switch project base directory path to Windows format before # executing Maven otherwise this will cause Maven not to consider it. if $cygwin ; then [ -n "$MAVEN_PROJECTBASEDIR" ] && MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` fi export MAVEN_PROJECTBASEDIR # Provide a "standardized" way to retrieve the CLI args that will # work with both Windows and non-Windows executions. MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" export MAVEN_CMD_LINE_ARGS exec "$JAVACMD" \ $MAVEN_OPTS \ $MAVEN_DEBUG_OPTS \ -classpath "${CLASSWORLDS_JAR}" \ "-Dclassworlds.conf=${MAVEN_HOME}/bin/m2.conf" \ "-Dmaven.home=${MAVEN_HOME}" \ "-Dlibrary.jansi.path=${MAVEN_HOME}/lib/jansi-native" \ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ ${CLASSWORLDS_LAUNCHER} "$@"
然后我們在cmd中測試一下,安裝和配置成功,當然了,我們必須先安裝Java的環境,maven的運行需要java的支持。
2.3、牛刀小試
我們用最土的辦法,一個個的創建符合Maven格式的文件夾,然后再來測試:
pom.xml:這個文件是我們和maven打交道的一個主要的渠道,通過對pom.xml進行編輯,可以實現我們之前說的定義包、版本、依賴等信息,並且能夠讓maven從中央倉庫去下載。這里要注意紅色部分,這些東西是我們自己編寫的程序的ID或者叫做坐標,可以唯一標定我們的程序。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <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/maven-v4_0_0.xsd"> 3 <modelVersion>4.0.0</modelVersion> 4 5 <groupId>maven.zyr</groupId> 6 <artifactId>maven01</artifactId> 7 <version>0.0.1-SNAPSHOT</version> 8 9 <dependencies> 10 <dependency> 11 <groupId>junit</groupId> 12 <artifactId>junit</artifactId> 13 <version>4.12</version> 14 </dependency> 15 16 </dependencies> 17 </project>
后面是包名:
1 package zyr.maven; 2 3 public class Hello{ 4 public String sayHello(){ 5 return "Hello Maven"; 6 } 7 }
另一個目錄:
1 package zyr.maven; 2 3 import org.junit.*; 4 5 public class TestClass{ 6 @Test 7 public void testHello(){ 8 System.out.println(new Hello().sayHello()); 9 } 10 }
於是整個結構是這樣:
到了這里我們就可以使用maven來編譯和測試了:
mvn compile
可以看到使用mvn編譯成功,得到了我們想要的結果,並且生成了編譯之后的目標文件,這樣我們就可以測試了。
使用mvn test我們測試一下程序的執行結果:
mvn test
可以看到測試成功得到了想要的結果。、
2.4、個人倉庫
之后我們可以將這個程序放到個人倉庫之中,使用
1 mvn install
但是此時這個倉庫默認是放在C盤的,如果以后裝機的時候不小心給忘記了,那么這些東西就沒有了,非常的麻煩,那我們需要怎么辦呢,在maven的安裝目錄之中有一個conf文件夾,里面有一個setting.xml文件,我們只需要修改這個文件的一點配置就可以了。將localRepository修改成我們想要存儲的位置就可以了。
之后我們可以看到已經按照我們的需要存放了:
2.5、自動生成目錄
每次都自己創建文件夾是一項非常粗笨的工作,因此肯定有插件可以幫我們實現的,那就是:
mvn archetype:generate
我們在新的文件之中使用這個命令,可以看到經過一段時間的下載之后,出現了交互界面,我們寫入自己需要定義的包名、程序名、版本號等坐標之后,這個插件自動為我們生成了這些東西,從此我們再也不用手工去忙碌了。
2.6、Maven的坐標、常用命令以及生命周期
坐標:maven 的所有構件均通過坐標進行組織和管理。maven 的坐標通過 5 個元素進行定義,其中 groupId、artifactId、version 是必須的,packaging 是可選的(默認為jar),classifier 是不能直接定義的。
maven使用groupId、artifactId、version唯一確定坐標,每個坐標都唯一的指向一個maven項目:
包名應與groupId+artifactId相吻合 groupId:項目組織唯一的標識符,一般為反寫的公司網址+項目名,跟 Java 包名類似,通常與域名反向一一對應。 artifactId:項目的唯一的標識符,一般為項目名+模塊名,定義當前 Maven 項目的一個模塊,默認情況下,Maven 生成的構件,其文件名會以 artifactId 開頭,如 hibernate-core-3.6.5.Final.jar。 version:版本號 x.x.x+版本類型 第一個x表示大版本號 第二個x表示分支版本號 第三個x表示小版本號(可省略) 常見版本類型: snapshot快照 alpha內部測試 beta公測 release穩定 GA正式發布
packaging:定義項目打包方式,如 jar,war,pom,zip ……,默認為 jar。
classifier:定義項目的附屬構件,如 hibernate-core-3.6.6.Final-sources.jar,hibernate-core-3.6.6.Final-javadoc.jar,其中 sources 和 javadoc 就是這兩個附屬構件的 classifier。classifier 不能直接定義,通常由附加的插件幫助生成。
常用命令:
mvn -v 查看maven版本及其他相關信息 compile 編譯maven項目,並生成target文件夾 test 運行test目錄下的測試文件,即測試 package 將項目打包,默認打包為jar格式,也可以打包成war格式用於服務器運行 install 將打包的jar文件安裝到maven本地倉庫(倉庫后面會詳細介紹) clean 刪除targert,相當於清除緩存
生命周期:
多個生命周期之間相互獨立。每個生命周期含有多個階段,階段按順序執行,運行后階段時,前階段會自動執行。 完整的項目構建構成包括: 清理、編譯、測試、打包、集成測試、驗證、部署 clean 清理項目,包括以下階段: pre-clean 執行清理前 clean 清理上一次構建生成的所有文件 post-clean 執行清理后的文件
default 構建項目(核心:常用),包括以下階段
-
- validate
- initialize
- generate-sources
- process-sources
- generate-resources
- process-resources :復制和處理資源文件到target目錄,准備打包;
- compile :編譯項目的源代碼;
- process-classes
- generate-test-sources
- process-test-sources
- generate-test-resources
- process-test-resources
- test-compile :編譯測試源代碼;
- process-test-classes
- test :運行測試代碼;
- prepare-package
- package :打包成jar或者war或者其他格式的分發包;
- pre-integration-test
- integration-test
- post-integration-test
- verify
- install :將打好的包安裝到本地倉庫,供其他項目使用;
- deploy :將打好的包安裝到遠程倉庫,供其他項目使用;
其中主要包括這幾個步驟:
compile 編譯 test 測試 packeage 打包 install 安裝
site 生成項目站點,根據pom中信息生成項目站點,包括以下階段 pre-site 在生成項目站點前要完成的工作 site生成項目的站點文檔 post-site在生成項目站點后要完成的工作 site-deploy發布生成的站點到服務器上
2.7、插件
可以說maven本身的源程序並不是很多,大部分功能都是來自於自己的插件,可以將插件綁定到生命周期的某個階段,從而在這個階段運行插件,生成相應的東西,比如我們經常使用的mvn package將程序編譯測試並且打包,如果將打包源代碼的插件綁定到這個階段就能在打包的時候生成源代碼的打包文件,非常的方便。
1 <build> 2 <plugins> 3 <plugin> 4 <groupId>org.apache.maven.plugins</groupId> 5 <artifactId>maven-source-plugin</artifactId> 6 <version>2.2.1</version> 7 <executions> 8 <execution> 9 <id>attach-source</id> 10 <phase>package</phase><!-- 要綁定到的生命周期的階段 --> 11 <goals> 12 <goal>jar-no-fork</goal><!-- 要綁定的插件的目標 --> 13 </goals> 14 </execution> 15 </executions> 16 </plugin> 17 </plugins> 18 </build>
當然了這些插件在本身就有默認的和生命周期的綁定,不同的項目有jar、war、pom等不同的打包方式,因此對應的有不同的綁定關系,其中針對default生命周期的jar包打包方式的綁定關系如下:
同時插件還可以動態地配置,不是一成不變的,這對我們的使用來說也是非常方便的,比如配置編譯的時候使用JDK1.7版本的環境。
1 <plugin> 2 <groupId>org.apache.maven.plugins</groupId> 3 <artifactId>maven-compiler-plugin</artifactId> 4 <configuration> 5 <source>1.7</source> 6 <target>1.7</target> 7 </configuration> 8 </plugin>
比如我們的平台是JDK1.8的,因此就會提示警告,但是這里注意沒有報錯。
同時插件也存儲在倉庫之中,在需要使用的時候會自動下載下來的。
2.8、pom.xml中常用標簽介紹以及maven依賴
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 3 <!-- 當前pom的版本--> 4 <modelVersion>4.0.0</modelVersion> 5 6 <!--坐標--> 7 <groupId>cn.edu</groupId> 8 <artifactId>maven04</artifactId> 9 <version>0.0.1-SNAPSHOT</version> 10 <!-- 默認是jar,其他war zip pom等 --> 11 <packaging>jar</packaging> 12 13 <!--項目描述名 --> 14 <name>maven04</name> 15 <!-- 項目地址 --> 16 <url>http://maven.apache.org</url> 17 18 <!-- 配置參數 --> 19 <properties> 20 <!-- 這里配置項目編譯編碼為UTF-8--> 21 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 22 </properties> 23 24 <!-- 開發人員信息 --> 25 <developers></developers> 26 <!-- 項目描述 --> 27 <description></description> 28 <!-- 許可信息 --> 29 <licenses></licenses> 30 <!-- 組織信息 --> 31 <organization></organization> 32 <!-- 依賴集,用於配置依賴 --> 33 <dependencies> 34 <dependency> 35 <groupId>junit</groupId> 36 <artifactId>junit</artifactId> 37 <version>3.8.1</version> 38 39 <!-- 依賴范圍:這個jar包只在范圍內生效,范圍外引用會報錯,這里讓junit只在test時被依賴。 40 其他一些情況,如:servlet-api.jar,在編譯階段需要引用,而在服務器運行階段則不需要引用,就可以使用scope--> 41 <scope>test</scope> 42 43 <!-- 默認為false,子項目將會繼承,true時子項目需要顯式引用 --> 44 <optional>false</optional> 45 46 <!-- 排除依賴列表:用於去除傳遞依賴等--> 47 <exclusions> 48 <exclusion></exclusion> 49 </exclusions> 50 51 52 </dependency> 53 </dependencies> 54 55 <!-- 依賴管理 56 為依賴進行統一管理,如果在父項目中聲明此標簽時,在子項目中不需聲明,確保父子項目依賴版本一致; 57 如子項目需要不同版本的依賴,只需在子項目中進行聲明即可,將會覆蓋父項目中的聲明。 58 --> 59 <!-- 60 <dependencyManagement> 61 <dependencies> 62 <dependency></dependency> 63 </dependencies> 64 </dependencyManagement> 65 --> 66 67 <!--配置構建時的屬性--> 68 <build> 69 <plugins></plugins> 70 </build> 71 72 <!-- 指定父模塊 --> 73 <!-- <parent></parent> --> 74 75 <!-- 用於聚合編譯多個maven模塊 --> 76 <modules></modules> 77 </project>
maven依賴(范圍、傳遞、沖突、排除、歸類):
執行不同的 Maven 命令(mvn package,mvn test,mvn install ……),會使用不同的 classpath,Maven 對應的有三套 classpath:編譯classpath、測試classpath,運行classpath。scope 選項的值,決定了該依賴構件會被引入到哪一個 classpath 中。
范圍:maven中提供了三種classpath:編譯、測試、運行 scope標簽 -compile 默認,編譯測試運行均有效,會傳遞 -provided 在編譯和測試時有效,如servletAPI可以加入,不傳遞 -runtime 在測試和運行時有效,如JDBCAPI可以加入 -test 在測試時有效,如junit可以加入 -system 在編譯和測試時有效,與本機系統相關聯,移植性差,在系統中以外部jar包的形式引入,不會在倉庫中查找 -import 導入,只能用在dependecyManagement中,表示從其他pom中導入dependecy的配置 傳遞: 如果C依賴B,B依賴A,那么C→B→A,那么此時C也會依賴A且會包含A中的依賴,這就是傳遞依賴。消除傳遞依賴:需要使用<exclusions>
沖突:
當多個傳遞性依賴中有對同一構件不同版本的依賴時,如何解決呢?
短路徑優先:假如有以下依賴:A -> B -> C ->X(版本 1.0) 和 A -> D -> X(版本 2.0),則優先解析較短路徑的 X(版本 2.0);
先聲明優先:若路徑長度相同,則誰先聲明,誰被解析。
依賴排除:
針對依賴沖突中的“短路徑優先”,如果我們想使用長路徑的依賴怎么辦呢?
這時可以使用依賴排除 <exclusions> 元素,顯示排除短路徑依賴。在非沖突的情況下,這種方法同樣有效。
依賴歸類:
通常在項目中,我們會同時依賴同一個構件的不同模塊,如 spring-orm-3.2.0,spring-context-3.2.0,且多個模塊版本相同,
為了維護和升級方便,我們可以對其同一管理,這時可以使用到 Maven 屬性,類似於變量的概念。
<properties> <springframework.version>3.2.0.RELEASE</springframework.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${springframework.version}</version> </dependency> </dependencies>
2.9、聚合和繼承
這里和我們設計模式之中的聚合和繼承是很類似的,只不過把主體從類變成了pom.xml文件而已。
聚合:在一個項目中,分模塊使用了maven,那么可能在這個項目中會有五六個,或者更多的maven項目存在。如果此時需要編譯或測試要怎么辦呢,進入每個maven項目中進行mvn compile么,那就要執行五六次的compile命令,十分繁瑣,這里就可以用maven的聚合來解決這個問題。
現有ABC三個工程,那么我們使用一個新的工程D,來聚合他們,以后只要對D進行編譯即可對三個工程同時進行編譯。使用module標簽進行聚合:
1 <modules> 2 <!--這里的路徑是基於D項目的pom.xml路徑,module標簽內為指向其他項目的pom文件的路徑 3 A、B、C、D項目在同一個文件夾內,那么從D內的pom中,通過../項目名,來找到其他項目的pom.xml--> 4 <module>../A</module> 5 <module>../B</module> 6 <module>../C</module> 7 </modules>
繼承:另一種情形,如果多個maven項目具有相同的依賴時或配置時,那么應該如何處理呢?這里就用到繼承的概念,在maven中使用<parent>標簽來進行繼承,比如建立一個項目,命名為parent,在parent的pom文件聲明一個common-io的依賴,不過這里用到了dependencyManagement:
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 3 <modelVersion>4.0.0</modelVersion> 4 5 <groupId>cn.edu</groupId> 6 <artifactId>parent</artifactId> 7 <version>0.0.1-SNAPSHOT</version> 8 <packaging>pom</packaging> 9 10 <name>parent</name> 11 <url>http://maven.apache.org</url> 12 13 <properties> 14 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 15 </properties> 16 17 <dependencies> 18 <dependency> 19 <groupId>junit</groupId> 20 <artifactId>junit</artifactId> 21 <version>4.12</version> 22 <scope>test</scope> 23 </dependency> 24 </dependencies> 25 26 <dependencyManagement> 27 <!-- 在這里聲明的依賴可以被子項目繼承引用 --> 28 <dependencies> 29 <dependency> 30 <groupId>commons-io</groupId> 31 <artifactId>commons-io</artifactId> 32 <version>2.4</version> 33 </dependency> 34 </dependencies> 35 </dependencyManagement> 36 </project>
在子項目中,配置繼承parent並使用parent中的common-io版本:
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 3 <modelVersion>4.0.0</modelVersion> 4 5 6 <groupId>cn.edu</groupId> 7 <artifactId>B</artifactId> 8 <version>0.0.1-SNAPSHOT</version> 9 <packaging>jar</packaging> 10 11 <name>B</name> 12 <url>http://maven.apache.org</url> 13 14 <properties> 15 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 16 </properties> 17 18 <!-- 在parent標簽中使用父項目的坐標進行配置 --> 19 <parent> 20 <groupId>cn.edu</groupId> 21 <artifactId>parent</artifactId> 22 <version>0.0.1-SNAPSHOT</version> 23 </parent> 24 25 <dependencies> 26 <!-- 此處使用依賴時,就不需聲明版本 --> 27 <dependency> 28 <groupId>commons-io</groupId> 29 <artifactId>commons-io</artifactId> 30 </dependency> 31 32 <dependency> 33 <groupId>junit</groupId> 34 <artifactId>junit</artifactId> 35 <version>4.12</version> 36 <scope>test</scope> 37 </dependency> 38 </dependencies> 39 </project>
三、將Maven程序放到Eclipse或者Myeclipse之中使用
到了這里我們才開始蹣跚學步第一步,前面的都是為了我們之后的使用和操作積累基礎的,那我們就來看看這個最常用的操作吧。
3.1、創建maven project
更改配置,使用我們自己的maven,不然myeclipse(我這里使用的是2014版)會使用默認的,內置的maven。
甚至我們還可以增加環境變量,不過對於已經在windows中配置過的,我們可以不用再次配置。
到了這里我遇到了一個問題,這個問題導致我昨天幾乎花了四五個小時還是一籌莫展,那就是我也按照網上的說明設置了這些參數,並且按照別人的創建方法創建了maven工程,選的是quickstart的,然后自定義了坐標,結果創建之后就是錯誤,有錯誤不可怕,我就一直在修復錯誤了,結果卻沒有一點改善的樣子,我嘗試了很多的方式一直都是這樣,再加上這個Myeclipse2014非常的占用內存,讓我真的很難接受,就這樣白白的浪費了時間,糟蹋了心情。由此可以看到一個好的IDE的重要性,可以讓我們把主要的精力放到自己關心的事情上面,而不是一直在這里調錯,改錯,結果改完這個錯誤那個錯誤又出現了。后來我暫時的放下了繼續往下做的念頭,到了今天,心情漸漸好轉,我又安裝了Myeclipse2017這個算是最新版的了,可以說是與時俱進的,當時的2014版,對maven的支持可以說是有很大的缺陷的,才導致了我們一直在這些傻瓜的錯誤上浪費時間,當我裝上了2017版本之后,一切都是那樣的簡單了,這就是好的IDE為我帶來的福利,這個2017版本不用配置maven環境就可以支持maven,因為它的內部早就集成了maven的環境,並且也集成了Tomcat的環境,因此這兩個東西不用配置就可以使用了呢,多么的強大呀,到這里我想說的是2014也集成了這些東西,可是真的很垃圾,maven一用就容易錯,Tomcat更是時不時的掛掉。因此,下面我們使用Myeclipse2017來講解。
在myeclipse2017中,我們不用配置maven環境,系統自帶的環境,我們可以查看是3.3.9的版本,可以看到embedded這個字樣,就是嵌入在2017內部的意思。然后我們不用任何配置,直接創建maven project。
我們使用mvn package命令來運行:
可以看到已經運行成功:
那么我們也可以根據自己的需要改成我們以前安裝的maven版本:
在1的地方我們隨便命名就可以,在2的地方,我們都不用填,相比於以前要寫一串環境變量的,這個IDE特別的強大。
然后我們再次運行:

[INFO] Scanning for projects... [INFO] [INFO] ------------------------< com.zyr.net:MyTest1 >------------------------- [INFO] Building MyTest1 0.0.1-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- maven-clean-plugin:3.0.0:clean (default-clean) @ MyTest1 --- [INFO] Deleting D:\workspace\MyTest1\target [INFO] [INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ MyTest1 --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory D:\workspace\MyTest1\src\main\resources [INFO] [INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ MyTest1 --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to D:\workspace\MyTest1\target\classes [INFO] [INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ MyTest1 --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory D:\workspace\MyTest1\src\main\resources [INFO] [INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ MyTest1 --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ MyTest1 --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory D:\workspace\MyTest1\src\test\resources [INFO] [INFO] --- maven-compiler-plugin:3.7.0:testCompile (default-testCompile) @ MyTest1 --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to D:\workspace\MyTest1\target\test-classes [INFO] [INFO] --- maven-surefire-plugin:2.20.1:test (default-test) @ MyTest1 --- [INFO] [INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running com.zyr.net.MyTest1.AppTest [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.094 s - in com.zyr.net.MyTest1.AppTest [INFO] [INFO] Results: [INFO] [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] [INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ MyTest1 --- [INFO] Building jar: D:\workspace\MyTest1\target\MyTest1-0.0.1-SNAPSHOT.jar [INFO] [INFO] --- maven-install-plugin:2.5.2:install (default-install) @ MyTest1 --- [INFO] Installing D:\workspace\MyTest1\target\MyTest1-0.0.1-SNAPSHOT.jar to D:\zyrLocalRepository\com\zyr\net\MyTest1\0.0.1-SNAPSHOT\MyTest1-0.0.1-SNAPSHOT.jar [INFO] Installing D:\workspace\MyTest1\pom.xml to D:\zyrLocalRepository\com\zyr\net\MyTest1\0.0.1-SNAPSHOT\MyTest1-0.0.1-SNAPSHOT.pom [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 9.799 s [INFO] Finished at: 2018-07-04T11:05:06+08:00 [INFO] ------------------------------------------------------------------------
可以看到和我們在命令行的結果是一致的,並且也按照我們的意願存儲在了我們指定的文件夾。
我們將文件進行更改:
1 package com.zyr.net.MyTest1; 2 3 public class App 4 { 5 public String sayHello( ) 6 { 7 return "Hello zyr!" ; 8 } 9 }
1 package com.zyr.net.MyTest1; 2 3 import org.junit.Test; 4 5 6 public class AppTest 7 { 8 @Test 9 public void myTest() 10 { 11 System.out.println("運行結果為:"+new App().sayHello()); 12 } 13 }
運行mvn test命令,這里有兩種方法,一種是直接運行->test,另一種是使用命令test,可以看到成功得到結果。
3.2、創建java項目然后使用maven
然后我們嘗試一下最常用的方式,這種方式拋棄了maven的代碼結構,我們首先創建java project,然后在src的上一層我們創建一個pom.xml,里面使用我們項目需要的依賴,如圖所示,然后我們使用項目->右鍵->config中的轉換成maven項目,之后就會自動增加依賴了,這樣之后我們按照自己的需要編寫java程序就可以了,然后運行的時候我們不使用maven來做,而是直接使用java的運行方式,使用這種方法,我們還可以將Tomcat的某些功能引入進來,構成我們的項目礦建,這樣就不用拘泥於maven的格式同樣能夠使用maven來給我們的項目帶來實惠了。
最后再提供一下依賴的查找網址:http://mvnrepository.com/、https://repository.sonatype.org/、http://search.maven.org/
四、總結
通過我們系統的學習,可以知道maven的原理,基本的構成,其中最重要的就是pom.xml文件的編寫了,如何實現依賴的組合,同時在大型項目中又如何避免以來帶來的沖突等問題,以及如何尋找我們需要的依賴,maven的生命周期,基本的使用方法,clean,compile,test,package,install等原理以及背后做的事情,通過這些學習我們將maven引入了myeclipse之中,更加的接近工程化開發方法,並且講解了如何使用,通過這樣的學習,我們關於maven的使用也算是漸入佳境了,需要注意的是我們最好使用最新版的myeclipse2017這樣可以幫助我們避免很多沒有理由的錯誤。