接著上文【IntelliJ Idea14 創建Maven多模塊項目,多繼承,熱部署配置總結(一)】,總結下項目熱部署和pom文件結構的一些要點:
一,依賴包的熱部署
上文中項目如果改了依賴包core模塊中的service服務代碼,重啟web服務是看不到改動效果的,這是因為依賴的core已經打成jar包給web模塊使用了,重啟并不會重新打jar包,所以只能重新package打包才能看到效果。
【解決方案】:把依賴的core模塊,編譯到web模塊里面去,在web下生成core的class文件,這樣重啟編譯就會實時更新界面了。
【未處理之前】:
配置模塊的
output layout
下的class
,選中對應的依賴右鍵,點擊put into output root
【處理之后,重新打包,啟動】:
有了class文件之后,重啟就能看到service的改動了。
此外Project Stucture
里面還有一些其他要注意的點:
1,【Modules】當項目的JDK是1.8的時候,配置每個module的Language Level
為對應的JDK的level;
2,【Facets】
檢查Facets右邊的【Deplyment Descriptors
】,必須是指向web.xml
檢查Facets右邊的【Web Resource Directories
】,必須是選中webapp
的目錄,類似普通非maven的項目需要指向WebRoot或者WebContent目錄
3,【Artifacts】就是上面的熱部署配置。
二,pom配置要點
2.1 pom的繼承
1,項目模塊可以一層一層的繼承下去,比如多層級的module方式:
module-test
--- module-test-common
--- module-test-platform
--- --- module-test-platform-A
--- --- module-test-platform-B
由上可知:
- module-test-platform-A和module-test-platform-B的parent是module-test-platform
- module-test-platform和module-test-common的parent是module-test
上面配置要實現的話,也很簡單,只需要將module-test-platform的pom.xml里面配置成<packaging>pom</packaging>
,然后module-test-platform-A和module-test-platform-B的parent都以來module-test-platform的GAV(maven三要素:groupId/artifactId/version)就行了。
<packaging>
不寫的話默認是jar,意思就是打成jar包;
寫pom的意思就是做父模塊,給子模塊繼承或者引用;
寫war的意思就是打成war包給tomcat啟動;
在Maven 中除了用繼承parent來做版本控制以外, 還可以通過 scope=import 來做版本控制.
Maven 2.0.9 添加了一個新特性: scope = import 也就是從外部導入依賴管理的依賴配置. 使用過 DependencyManagement都知道, 多模塊構建項目的時候, 為了解決各模塊依賴版本一致, 統一在父pom.xml文件中統一定義各個依賴jar文件的版本, 然后子模塊通過引用的方式添加需要的依賴jar, 但隨著項目工程越來越大, 添加的依賴文件也越來也多, 父pom.xml的 DependencyManagement 也會越來越長, 不便于管理. 另外, 因為pom.xml 是單繼承的, 如果已經有一個父pom.xml了, 想要再引用外部的pom.xml, 就只能復制到父pom.xml中了. 因此采用在 DependencyManagement 中使用scope = import的方式可以分類引入更多的管理配置, 也擺脫了單繼承的限制.
使用import scope解決maven繼承(單)問題
想必大家在做SpringBoot應用的時候,都會有如下代碼:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
</parent>
繼承一個父模塊,然后再引入相應的依賴
假如說,我不想繼承,或者我想繼承多個,怎么做?
我們知道Maven的繼承和Java的繼承一樣,是無法實現多重繼承的,如果10個、20個甚至更多模塊繼承自同一個模塊,那么按照我們之前的做法,這個父模塊的dependencyManagement會包含大量的依賴。如果你想把這些依賴分類以更清晰的管理,那就不可能了,import scope依賴能解決這個問題。你可以把dependencyManagement放到單獨的專門用來管理依賴的pom中,然后在需要使用依賴的模塊中通過import scope依賴,就可以引入dependencyManagement。例如可以寫這樣一個用于依賴管理的pom:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.test.sample</groupId>
<artifactId>base-parent1</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactid>junit</artifactId>
<version>4.8.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactid>log4j</artifactId>
<version>1.2.16</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
然后我就可以通過非繼承的方式來引入這段依賴管理配置
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test.sample</groupId>
<artifactid>base-parent1</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>junit</groupId>
<artifactid>junit</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactid>log4j</artifactId>
</dependency>
注意:import scope只能用在dependencyManagement里面
這樣,父模塊的pom就會非常干凈,由專門的packaging為pom來管理依賴,也契合的面向對象設計中的單一職責原則。此外,我們還能夠創建多個這樣的依賴管理pom,以更細化的方式管理依賴。這種做法與面向對象設計中使用組合而非繼承也有點相似的味道。
那么,如何用這個方法來解決SpringBoot的那個繼承問題呢?
配置如下:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.3.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
這樣配置的話,自己的項目里面就不需要繼承SpringBoot的module了,而可以繼承自己項目的module了。
參考:https://blog.csdn.net/mn960mn/article/details/50894022
2.2 dependencies與dependencyManagement的區別
在我們項目頂層的POM文件中,我們會看到dependencyManagement元素。通過它元素來管理jar包的版本,讓子項目中引用一個依賴而不用顯示的列出版本號。Maven會沿著父子層次向上走,直到找到一個擁有dependencyManagement元素的項目,然后它就會使用在這個dependencyManagement元素中指定的版本號。
這樣做的好處:統一管理項目的版本號,確保應用的各個項目的依賴和版本一致,才能保證測試的和發布的是相同的成果,因此,在頂層pom中定義共同的依賴關系。同時可以避免在每個使用的子項目中都聲明一個版本號,這樣想升級或者切換到另一個版本時,只需要在父類容器里更新,不需要任何一個子項目的修改;如果某個子項目需要另外一個版本號時,只需要在dependencies中聲明一個版本號即可。子類就會使用子類聲明的版本號,不繼承于父類版本號。
區別:
dependencies即使在子項目中不寫該依賴項,那么子項目仍然會從父項目中繼承該依賴項(全部繼承)
dependencyManagement里只是聲明依賴,并不實現引入,因此子項目需要顯示的聲明需要用的依賴。如果不在子項目中聲明依賴,是不會從父項目中繼承下來的;只有在子項目中寫了該依賴項,并且沒有指定具體版本,才會從父項目中繼承該項,并且version和scope都讀取自父pom;另外如果子項目中指定了版本號,那么會使用子項目中指定的jar版本。
2.3 Maven依賴Scope選項詳解
在一個maven項目中,如果存在編譯需要而發布不需要的jar包,可以用scope標簽,值設為provided。
如下:
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.3</version>
<scope>provided</scope>
</dependency>
Scope的其他參數如下:
compile:默認的scope,表示 dependency 都可以在生命周期中使用。
而且,這些dependencies 會傳遞到依賴的項目中。適用于所有階段,會隨著項目一起發布
provided:跟compile相似,但是表明了dependency 由JDK或者容器提供,例如Servlet AP和一些Java EE APIs。這個scope 只能作用在編譯和測試時,同時沒有傳遞性,即:child module無法引用。
runtime:表示dependency不作用在編譯時,但會作用在運行和測試時,如JDBC驅動,適用運行和測試階段,與provided相反。
test:表示dependency作用在測試時,不作用在運行時。 只在測試時使用,用于編譯和運行測試代碼。不會隨項目發布。
system:跟provided 相似,但是在系統中要以外部JAR包的形式提供,maven不會在repository查找它。
2.4 Maven的classifier作用
classifier可以是任意的字符串,用于拼接在GAV之后來確定指定的文件。
可用于區分不同jdk版本所生成的jar包
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.2.2</version>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.2.2</version>
<classifier>jdk13</classifier>
</dependency>
實際上對應的jar包是json-lib-2.2.2-jdk15.jar
和json-lib-2.2.2-jdk13.jar
。
區分項目的不同組成部分,例如:源代碼、javadoc、類文件等。
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.2.2</version>
<classifier>jdk15-javadoc</classifier>
</dependency>
對應的是json-lib-2.2.2-jdk15-javadoc.jar
。
需要注意classifier的位置
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<classifier>jdk15-javadoc</classifier>
<version>2.2.2</version>
</dependency>
對應的是json-lib-jdk15-javadoc-2.2.2.jar
。可能會出現找不到jar包的情況。