最近在負責的是一個比較複雜項目,模塊不少,代碼中的二級模塊就有9個,部分二級模塊下面還分了多個模塊。代碼中的多模塊是用maven管理的,每一個模塊都使用spring boot框架。以前有零零散散學過一些maven多模塊配置的知識,但沒本身從頭至尾建立和配置過,也快忘得差很少了。此次正好對照着這個項目,動手實踐一下,下面咱們就開始吧。html
maven多模塊項目一般由一個父模塊和若干個子模塊構成,每一個模塊都對應着一個pom.xml。它們之間經過繼承和聚合(也稱做多模塊)相互關聯。多模塊適用於一些比較大的項目,經過合理的模塊拆分,實現代碼的複用,便於維護和管理。java
由於本系列的下一篇是《Spring Boot集成Dubbo》,因此本章就以建立多模塊的dubbo項目做爲示例。示例中的開發環境是Win 7,編輯器是Intellij IDEA,Java版本是1.8。web
首先咱們在IDEA中建立一個spring boot工程做爲父項目。spring
1、在界面左上角選擇File->New->Project後,選擇Spring Initializr,默認使用的Java版本是1.8。
apache
2、點擊Next,進入下一步,能夠設置項目的一些基本信息。tomcat
這裏咱們先來溫習下groupId、artifactId、package這三個參數的通常填寫規範。springboot
groupId和artifactId統稱爲「座標」,是爲了保證項目惟一性而提出的。groupId是項目組織惟一的標識符,實際對應JAVA的包的結構,ArtifactID是項目的惟一的標識符,實際對應項目的名稱,就是項目根目錄的名稱。groupId通常分爲多個段,通常第一段爲域,第二段爲公司名稱。舉個apache公司的tomcat項目例子:這個項目的groupId是org.apache,它的域是org,公司名稱是apache,artifactId是tomcat。包結構package最好是以groupId.artifactId打頭的。框架
由於後續打算將「代碼學習和實踐」寫成一個系列的文章,文中演示的工程都做爲該工程的子模塊,因此這裏項目名Name就填寫CodeLearnAndPractice。maven
這裏是我的練習的項目,不涉及公司名,但groupId、artifactId、package參數的填寫,仍是儘可能按照上面的規範來填寫,這裏package就直接用groupId.artifactId。以下所示:編輯器
3、點擊Next,進入下一個選擇dependency的界面,做用是在pom中自動添加一些依賴,在項目開始時就下載。這裏咱們暫時不勾選任何依賴。
4、點擊Next,進入下一個界面,填寫工程名,並選擇工程所在目錄。填寫完成後,點擊Finish,便可建立一個spring boot項目。
在上面建立好的CodeLearnAndPractice工程名上,點擊右鍵,選擇New–>Module,進入New Module頁面。
該模塊爲dubbo服務的提供方,Name爲springboot-dubbo-server,後面其餘的參數均可參照父模塊的參數設置。
下面建立另外一個Module,dubbo服務的調用方,Name爲springboot-dubbo-client,其餘參數設置參照上步。
以上3個模塊建立完成以後,整個項目的目錄結構以下圖所示。
咱們把下圖選中的無用的文件及文件夾刪掉,包括三個模塊的mvnw、mvnw.cmd文件及.mvn文件夾,還有父模塊的src目錄,由於此處的父模塊只作依賴管理,不須要編寫代碼。
到這裏,一個父模塊和兩個子模塊都建立完成啦~~
父pom是爲了抽取統一的配置信息和依賴版本控制,方便子pom直接引用,簡化子pom的配置。
下面介紹下父pom的配置中須要注意的一些地方。我貼出的pom看起來會有點冗餘,由於其中一些不須要的地方,我沒有直接刪掉而是註釋掉,並加了說明,是爲了後續查看的時候還能清楚刪掉的緣由。
多模塊項目中,父模塊打包類型必須是pom,同時以給出全部的子模塊,其中每一個module,都是另一個maven項目。
咱們的項目中目前一共有兩個子模塊,springboot-dubbo-server和springboot-dubbo-client。後續新增的子模塊也必須加到父pom的modules中。
繼承是maven中很強大的一種功能,繼承可使子pom得到parent中的各項配置,對子pom進行統一的配置和依賴管理。父pom中的大多數元素都能被子pom繼承,想深刻了解的同窗可自行搜索學習~~
maven項目之間的繼承關係經過表示。這裏使用的開發框架是spring boot,默認繼承spring-boot-starter-parent。
通常在項目最頂層的父pom中使用該元素,讓全部子模塊引用一個依賴而不用顯式的列出版本號。maven會沿着父子層次向上走,直到找到一個擁有dependencyManagement元素的項目,而後它就會使用在這個dependencyManagement元素中指定的版本號。
在properties標籤中,添加各依賴包的版本號,而後在dependency中直接引用該依賴版本號的值便可。
CodeLearnAndPractice/pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.practice</groupId> <artifactId>CodeLearnAndPractice</artifactId> <version>0.0.1-SNAPSHOT</version> <!--<packaging>jar</packaging>--> <packaging>pom</packaging> <!--父模塊打包類型必須爲pom--> <modules> <module>springboot-dubbo-server</module> <module>springboot-dubbo-client</module> </modules> <name>CodeLearnAndPractice</name> <description>Practice the learned code</description> <!-- parent指明繼承關係,給出被繼承的父項目的具體信息--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <!-- 在properties中統一控制依賴包的版本,更清晰--> <dubbo.version>2.5.3</dubbo.version> <zkclient.version>0.10</zkclient.version> </properties> <dependencyManagement> <!--dependencyManagement用於管理依賴版本號--> <dependencies> <!-- 刪除spring-boot-starter和spring-boot-starter-test, 由於parent中繼承的祖先中已經有了,而且通常dependencyManagement管理的依賴都要寫版本號 --> <!--<dependency>--> <!--<groupId>org.springframework.boot</groupId>--> <!--<artifactId>spring-boot-starter</artifactId>--> <!--</dependency>--> <!--<dependency>--> <!--<groupId>org.springframework.boot</groupId>--> <!--<artifactId>spring-boot-starter-test</artifactId>--> <!--<scope>test</scope>--> <!--</dependency>--> <!--新增後續dubbo項目中所需依賴,dubbo、zk--> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <!--<version>2.5.3</version>--> <!--使用properties中配置的版本號--> <version>${dubbo.version}</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <!--<version>0.10</version>--> <!--使用properties中配置的版本號--> <version>${zkclient.version}</version> </dependency> </dependencies> </dependencyManagement> <!--該插件做用是打一個可運行的包,必需要寫在須要打包的項目裏。這裏的父模塊不須要打包運行,因此刪掉該插件。--> <!--<build>--> <!--<plugins>--> <!--<plugin>--> <!--<groupId>org.springframework.boot</groupId>--> <!--<artifactId>spring-boot-maven-plugin</artifactId>--> <!--</plugin>--> <!--</plugins>--> <!--</build>--> </project>
子模塊的parent要使用頂層的父模塊.
父模塊pom中使用dependencyManagement來管理的依賴,在子模塊pom中就不須要再寫版本號了,exclusion元素也不須要再寫。
springboot-dubbo-server\pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.practice</groupId> <artifactId>springboot-dubbo-server</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springboot-dubbo-server</name> <description>Demo project for Spring Boot</description> <!-- 子模塊的parent要使用頂層的父模塊--> <parent> <!--<groupId>org.springframework.boot</groupId>--> <!--<artifactId>spring-boot-starter-parent</artifactId>--> <!--<version>1.5.8.RELEASE</version>--> <!--<relativePath/>--> <groupId>com.practice</groupId> <artifactId>CodeLearnAndPractice</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <!-- properties可刪掉,會繼承父模塊的--> <!--<properties>--> <!--<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>--> <!--<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>--> <!--<java.version>1.8</java.version>--> <!--</properties>--> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--新增後續dubbo項目中所需依賴,dubbo、zk。 父模塊pom中使用dependencyManagement來管理依賴版本號,子模塊pom中不須要再寫版本號,exclusion也不須要--> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <!--<version>2.5.3</version>--> <!--<exclusions>--> <!--<exclusion>--> <!--<groupId>org.springframework</groupId>--> <!--<artifactId>spring</artifactId>--> <!--</exclusion>--> <!--</exclusions>--> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <!--<version>0.10</version>--> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
springvoot-dubbo-client/pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.practice</groupId> <artifactId>springboot-dubbo-client</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springboot-dubbo-client</name> <description>Demo project for Spring Boot</description> <!-- 子模塊的parent要使用頂層的父模塊--> <parent> <!--<groupId>org.springframework.boot</groupId>--> <!--<artifactId>spring-boot-starter-parent</artifactId>--> <!--<version>1.5.8.RELEASE</version>--> <!--<relativePath/>--> <groupId>com.practice</groupId> <artifactId>CodeLearnAndPractice</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <!-- properties可刪掉,會繼承父模塊的--> <!--<properties>--> <!--<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>--> <!--<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>--> <!--<java.version>1.8</java.version>--> <!--</properties>--> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 該模塊須要啓動web服務,須要該依賴--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--新增後續dubbo項目中所需依賴,dubbo、zk 父模塊pom中使用dependencyManagement來管理依賴版本號,子模塊pom中不須要再寫版本號 父模塊pom中裏有exclusion,子模塊pom中不要寫exclusion--> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <!--<version>2.5.3</version>--> <!--<exclusions>--> <!--<exclusion>--> <!--<groupId>org.springframework</groupId>--> <!--<artifactId>spring</artifactId>--> <!--</exclusion>--> <!--</exclusions>--> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <!--<version>0.10</version>--> </dependency> <!--client模塊須要依賴server模塊--> <dependency> <groupId>com.practice</groupId> <artifactId>springboot-dubbo-server</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
當dependency A自身的依賴B,與其餘dependency存在衝突的時候(最多見的就是版本衝突),咱們就須要把B排除掉,這時就須要使用exclusions元素。
那麼咱們怎麼知道一個dependency自身包含哪些依賴呢?
一、經過mvn dependency:tree命令查看依賴樹
二、使用IDEA或其餘IDA查看依賴樹
點擊IDEA右側的Maven Projects,在每一個模塊的Dependencies中便可查看每一個dependency內部的依賴及版本號,歷來識別哪些依賴須要被排除掉。
以dubbo爲例,咱們先刪除配置,點開Maven Projects,能夠看到2.5.3版本的dubbo中使用的spring版本是2.5.6,這是一個很老的版本,有一些方法是沒有的,如今在用的spring版本通常都是4.*的,因此咱們須要把它排除掉,避免後續報錯。
要查看當前項目中使用的spring版本,能夠按住左鍵,而後點擊父pom中的值,進入更上一層pom,再重複上步操做,能夠看到spring的版本是4.3.12。
按住左鍵,而後點擊父pom中的值,進入更上一層pom:
能夠看到spring的版本是4.3.12:
這裏就先不寫代碼了,到下一章再寫。直接編譯一下,若是編譯成功,說明pom文件的配置沒有什麼大問題。
點開右側Maven Projects,雙擊父模塊Lifecycle中的compile,進行代碼編譯,或者直接在Terminal中執行命令:mvn compile。
編譯經過啦~~
到這裏,Spring Boot多模塊項目建立與配置就介紹完啦。
這樣一個過程實踐下來,再去看開發的代碼結構,應該會輕鬆很多吧~~~
參考文檔:
https://testerhome.com/topics/11359