我們講完構建相關的的核心知識,接下來我們進入 maven 是如何管理套件以及套見衝突時的解決方式。Dependency Scope 即依賴範圍,它有兩個主要功能
今日就先來談談第一點吧
我們先用 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
前言提到第一點「決定相依套件是否加到 classpath 中」,試想整個專案的構建classpath可以分為三個部分,Dependency Scope就是決定下面三個時期的作用域
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中
官方並不建議使用system scope,且已被官方列示為deprecated,原因在於它並不從Maven倉庫中查找出來,屆時構建會發生什麼事情沒能人保證對吧!!
使用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
修改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>
我們可以在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>
本日介紹了各個Dependency Scope的作用的runtime時期,並以WAR打包的方式驗證Scope的行為,加以說明實務上常會與到的私有Jar套件的處理方式。