iT邦幫忙

2025 iThome 鐵人賽

DAY 10
0
Software Development

我們與Maven的距離系列 第 13

Day12 - Dependency Scope

  • 分享至 

  • xImage
  •  

前言

我們講完構建相關的的核心知識,接下來我們進入 maven 是如何管理套件以及套見衝突時的解決方式。Dependency Scope 即依賴範圍,它有兩個主要功能

  1. 決定相依套件是否加到 classpath 中
  2. 作為依賴傳遞的規則

今日就先來談談第一點吧

前置作業

我們先用 maven 創建一個 web 專案方便我們進行 dependency 說明

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DarchetypeVersion=1.5

專案目錄結構如下

mywebapp
    |   pom.xml
    |
    +---.mvn
    |       jvm.config
    |       maven.config
    |
    \---src
        \---main
            \---webapp
                |   index.jsp
                |
                \---WEB-INF
                        web.xml

創建lib資料夾,放入MyApp-1.0.0.jar

Dependency Scope

前言提到第一點「決定相依套件是否加到 classpath 中」,試想整個專案的構建classpath可以分為三個部分,Dependency Scope就是決定下面三個時期的作用域

  1. 編譯時期的classpath
  2. 測試時期的classpath
  3. 運行時期的classpath
scope compile classpath test classpath runtime classpath 範例
compile Y Y Y 大多數套件皆為此scope
test - Y - Junit套件
provided Y Y - 已由container提供,例如servlet-api
runtime - Y Y 只有執行環境需要,例如JDBC實作套件
system Y Y - 本地端載入的套件非存在於Maven Repository,例如廠商開發的私有Jar

備註:預設的scope為comile,可以省略,另外套件相依的範圍總共有 6 種,其中 import 只能用在 中,用來匯入 BOM,這部分留到後面用到時再介紹

範例

WAR 在打包時,會根據 dependency scope 來決定哪些 JAR 會被放進去,所以藉由此我們可以驗證scope是否正確,撰寫pom.xml

<dependencies>
        <!-- compile:會放進 WEB-INF/lib -->
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.59</version>
        </dependency>

        <!-- provided:容器提供,不會打包進 WAR -->
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>5.0.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- runtime:只在執行期需要,會放進 WEB-INF/lib -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
            <scope>runtime</scope>
        </dependency>

        <!-- test:只在測試時用,不會放進 WAR -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>

        <!-- system:指定本地 jar,會放進 WEB-INF/lib -->
        <dependency>
            <groupId>com.mycompany</groupId>
            <artifactId>MyApp</artifactId>
            <version>1.0.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/lib/MyApp-1.0.0.jar</systemPath>
        </dependency>
    </dependencies>

執行

mvn package

確認打包的套件只有mysql、fastjson相依套件被打包到war中
https://ithelp.ithome.com.tw/upload/images/20250927/20128084leGRiJt2PI.png

情境題1.你會說就是需要加入廠商的私有Jar,這樣WAR檔沒辦法RUN啊!!

官方並不建議使用system scope,且已被官方列示為deprecated,原因在於它並不從Maven倉庫中查找出來,屆時構建會發生什麼事情沒能人保證對吧!!

解法1.

使用install的方式將私有jar安裝置本地倉庫,如此一來我們就不用設置scope為system

mvn install:install-file -Dfile=".\lib\MyApp-1.0.0.jar" "-DgroupId=com.mycompany" "-DartifactId=MyApp" "-Dversion=1.0.0" "-Dpackaging=jar" "-DcreateChecksum=true"

本地倉庫就會看到install的私有jar
https://ithelp.ithome.com.tw/upload/images/20250927/20128084HJEQSPvIoY.png
修改pom.xml

<dependency>
            <groupId>com.mycompany</groupId>
            <artifactId>MyApp</artifactId>
            <version>1.0.0</version>
            <!-- <scope>system</scope>
            <systemPath>${project.basedir}/lib/MyApp-1.0.0.jar</systemPath> -->
        </dependency>

day12_dependency_03

解法2.

我們可以在build標籤中調整plugin的處理方式,請參考如下

<build>
  <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <configuration>
          <webResources>
            <resource>
              <directory>${project.basedir}/lib</directory>
              <targetPath>WEB-INF/lib</targetPath>
            </resource>
          </webResources>
        </configuration>
      </plugin>
    </plugins>
</build>

https://ithelp.ithome.com.tw/upload/images/20250927/20128084nROQI8Q25t.png

小結

本日介紹了各個Dependency Scope的作用的runtime時期,並以WAR打包的方式驗證Scope的行為,加以說明實務上常會與到的私有Jar套件的處理方式。

Reference


上一篇
Day11 - Maven lifecycle
下一篇
Day13 - Transitive Dependencies
系列文
我們與Maven的距離16
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言