天天看點

Maven scope 依賴範圍詳解

Maven的生命周期存在編譯、測試、運作、打包這些過程,那麼顯然有些依賴隻用于測試(test),比如

junit

有些依賴編譯用不到,隻有運作的時候才能用到( runtime ),比如 mysql 驅動包在編譯期就用不到,而是在運作時用到的;

還有些依賴在編譯期要用到,而運作期不需要提供(provided),因為有些容器已經提供了,比如

servlet-api

在 tomcat 中已經提供了,我們隻需要的是編譯期提供而已。

總結說來,在POM 4中,

<dependency>

中還引入了

<scope>

,它主要管理依賴的部署。大緻有

compile、provided、runtime、test、system

等幾個。

  1. compile:預設的scope,參與目前項目的編譯、測試、運作、打包等 全過程 參與。 (程式員寫的業務代碼)
  2. provided:編譯、測試階段存在,不會打入包中。(

    servlet-api.jar

    JDK

  3. runtime:編譯不需要,在運作、打包階段參與。(

    mysql.jar

    驅動)
  4. test:測試需要,不會打入包中。(

    junit.jar

  5. system:不是從本地maven倉庫引入,而是在本地目錄的下的jar,與provided 相似 。一般不使用。 (oracle 驅動

    ojdbc14.jar

<dependency>
    <groupId>groupId</groupId>
    <artifactId>artifactId</artifactId>
    <version>N</version>
    <scope>...</scope>
</dependency>
           

1.1、compile 模式 (預設,全過程參與)

預設就是 compile。

compile 需要參與目前項目的編譯、測試、運作、打包。

1.2、provided(編譯、測試階段存在,打包時排除)

provided 隻存在編譯、運作、測試階段,打包是不用包括進去,打包階段做了 exclude 動作,因為别的容器能提供對應的依賴。

應用場景:

定義了一個Servlet,此時需要

servlet-api.jar

才能編譯成功,但是當你達成war 包時,你并不想将

servlet-api.jar

包進去,因為Tomcat等容器會提供。此時用到 provided 。

provided 隻在編譯、運作、測試階段,打包是不用包進去,打包階段做了排除。

provided 打包的時候可以不用包含進去,因為别的容器(Web Container)會提供。

阿裡開發規範文檔:如果依賴其它二方庫,盡量是 provided 引入,讓二方庫使用者去依賴具體版本号; 無 log 具體實作,隻依賴日志架構。

例如 : 添加

<scope>provided</scope>

,因為provided表明該包隻在編譯和測試的時候用,是以,當啟動tomcat 的時候,就不會沖突了。

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>1.0-alpha-1</version>
    <scope>provided</scope>
</dependency>
           

1.3、runtime 模式(跳過編譯,運作和打包參與)

runtime 表示被依賴項目無需參與項目的編譯,不過後期的測試、運作和打包周期需要其參與。

與compile相比,runtime 跳過編譯而已。

比如,你可能在編譯的時候隻需要

JDBC API JAR

,而隻有在運作的時候才需要 JDBC 驅動實作。

編譯時該包不參與,運作時參與。

1.4、test 模式(測試階段有效)

test 範圍依賴 在一般的編譯和運作時都不需要,它們隻有在測試編譯和測試運作階段可用。比如

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <scope>test</scope>
</dependency>
           

1.5、system (依賴于本地目錄中,與provided 相似)

system 不是依賴于 maven倉庫、本地maven倉庫,而是從本地磁盤指定路徑下尋找,需要 systemPath 屬性。

與 provided 相似,不過不依賴maven倉庫,而是從本地檔案系統讀取。

1)方式1、引入本地磁盤目錄下的jar包

<dependency>
    <!--自定義-->
    <groupId>com.im</groupId> 
    <!--自定義-->
    <artifactId>sdk</artifactId>   
    <!--自定義-->
    <version>1.0</version>
    <!--system,類似provided,需要顯式提供依賴的jar以後,Maven就不會在Repository中查找它-->
    <scope>system</scope>
    <!--項目根目錄下的lib檔案夾下-->
    <systemPath>${basedir}/lib/sdk-1.0.jar</systemPath>
</dependency>
           

2)方式2、編譯階段指定外部 lib

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.1.2</version>
    
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <encoding>UTF-8</encoding>
        
        <compilerArguments>
            <!--指定外部lib-->
            <extdirs>lib</extdirs>
        </compilerArguments>        
    </configuration>
</plugin>
           

2、将外部 jar 導入本地 maven 倉庫

有一些收費的,或都其他途徑擷取的jar 在maven倉庫中不存在, 如果想通過maven使用時,可以先将jar導入到本地的maven倉庫中,如下:

mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc14  -Dversion=10.2.0.5.0 -Dpackaging=jar -Dfile=.\ojdbc14_10.2.0.5.0.jar
           

再引入jar包:

<dependency>
    <groupId>com.oracle</groupId>
    <artifactId>ojdbc14</artifactId>
    <version>10.2.0.5.0</version>
</dependency>
           

3、maven預定義内置屬性

${basedir}          表示項目根目錄,即包含 pom.xml 檔案的目錄;
${version}          表示項目版本;
${project.basedir}  同${basedir};
${project.baseUri}  表示項目檔案位址;
${maven.build.timestamp}  表示項目構件開始時間;
${maven.build.timestamp.format}  表示屬性 ${maven.build.timestamp}  的展示格式,預設值為 yyyyMMdd-HHmm ,可自定義其格式
           

4、scope 的傳遞依賴

A -> B -> C, 目前項目 A,A依賴于B,B依賴于C,知道B在A中的scope,怎麼知道 C在 A 中的 scope,
即,A需不需要 C的問題,本質由 C在B中的scope決定
當 C 在 B 中的scope 是test 或 provided 時,C 直接被丢棄,A不依賴C
否則 A 依賴 C,C的scope 繼承與B 的scope 
           

繼續閱讀