第一章:Maven簡介
沒有人會牴觸優秀的技術,除非缺乏文檔、學習成本高。
構建(build):包括編譯、單元測試、文檔生成、打包、部署等。
Maven是構建工具、依賴管理工具、項目信息管理工具。
Make和Ant是過程式的,Maven是聲明式的;Make不易實現跨平臺構建,Ant沒有依賴管理。
第二章:Maven的安裝和配置
Maven安裝目錄文件解析:
- bin。包含mvn運行的腳本。這些腳本用來配置Java命令,準備好classpath和相關的Java系統屬性,然後執行Java命令。mvn是基於UNIX平臺的shell腳本,mvn.bat則是基於Windows平臺的bat腳本。
- boot。類加載器框架,用來加載自己的類庫。
- conf。Setting文件全局地控制Maven的行爲,是最重要的部分。
- lib。Maven運行時所需要的Java類庫。還包括超級POM。
- 其他文件。包括LICENSE.txt、NOTICE.txt、README.txt。
不建議使用IDE自帶的Maven:
- 通常該Maven版本較新,非穩定版。
- 可能與命令行Maven版本不一致,從而造成構建不一致。
第三章:Maven使用入門
Maven的POM(Project Object Model),相當於Make的Makefile,Ant的build.xml。
第四章:背景案例
跳過。
第五章:座標和依賴
Maven採用座標機制來管理構建。(聯想:如果軟件安裝包也可以使用這個機制就好了,不過現在公司一般都會放在內網上。)
座標:
- groupId。當前Maven項目所屬的實際項目。例如com.companyName.projectName。
- artifacId。實際項目中的Maven項目(模塊)。例如projectName-modularName。
- version。版本。
- packaging。打包方式。
- classifier。用於協助輸出附屬構件。
依賴的配置:
- groupId、artifactId、version。即座標。
- type。類型,相當於packaging。
- scope。範圍,控制與編譯、測試、運行classpath的關係。包括compile(默認值,編譯範圍,3種classpath都有效)、test(僅測試classpath有效,例如JUnit)、provided(已提供依賴範圍,編譯和測試有效,運行無效,例如servlet-api,運行時容器已提供)、runtime(測試運行有效,編譯無效,例如JDBC驅動實現)、system(與本機系統綁定,不推薦使用)、import(聚合工程中可能用到)。
- optional。是否可選。
- exclusions。排除傳遞性依賴。
傳遞性依賴和依賴範圍:
依賴調解:當同一個構件被多次引用時,首先採用最短路徑優先原則,如果路徑長度相同,則採用最先聲明優先原則。
排除依賴:傳遞性依賴會導致隱士地引入很多依賴,有時也會造成問題。可通過以下方式解決。
<dependencies>
<dependency>
<groupId>com.companyName.projectName</groupId>
<artifactId>projectName-modularName</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>com.companyName.projectName</groupId>
<artifactId>projectName-anotherModularName</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.companyName.projectName</groupId>
<artifactId>projectName-anotherModularName</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
優化依賴:
- mvn dependency:list。查看已解析依賴。
- mvn dependency:tree。依賴樹。
- mvn dependency:analyze。分析依賴。
第六章:倉庫
座標可理解爲構件的邏輯地址,倉庫則爲構件的物理地址。
超級POM:
<repositories>
<repository>
<id>central</id>
<name>Maven Repository Switchboard</name>
<url>http://repo1.maven.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
<snapshots>
</repository>
</repositories>
快照版本僅在組織內部的項目或模塊間依賴使用,例如兩位同學同時開發模塊A和B,並且有依賴關係,其餘時候都應避免使用快照版本。快照版本會在版本號後面加上時間戳。
鏡像倉庫會完全屏蔽掉被鏡像倉庫,如果鏡像倉庫不可用,Maven將無法下載構件。
第七章:生命週期和插件
Maven的3種生命週期:clean、default、site。
生命週期與插件目標:
可自定義綁定生命週期與插件目標。可通過命令行、POM進行插件配置。
第八章:聚合與繼承
通過<modules>標籤實現聚合:
<!-- account-aggregator的POM -->
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.companyName.projectName</groupId>
<artifactId>account-aggregator</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>account-email</module>
<module>account-persist</module>
</modules>
</project>
通過<parent>標籤實現繼承:
<!-- account-email的POM-->
<project>
<parent>
<groupId>com.companyName.projectName</groupId>
<artifactId>account-parent</artifactId>
<version>1.0.0</version>
<relativePath>../account-parent/pom.xml</relativePath>
</parent>
</project>
聚合與繼承:聚合方便快速構建項目,繼承減少重複配置。兩者除了POM以外沒有別的內容。
<dependencyManagement>標籤:能讓子模塊繼承到父模塊的依賴配置,又能保證子模塊的靈活性。子模塊如果編寫了該<dependency>,則不需要編寫版本號,由父模塊統一管理;如果沒有編寫該<dependency>,同樣也不會引入依賴。
常見的可被繼承的POM元素:groupId、version、distributionManagement、properties、dependencies、dependencyManagement、repositories、build。
Maven反應堆(Reactor):所有模塊所組成的構建結構,以及各模塊之間的繼承與依賴關係。
可通過輸出查看構建順序,如果模塊A繼承模塊B,則優先構建模塊B。當模塊A和B互相繼承則會報錯。
第九章:使用Nexus創建私服
私服的好處:降低中央倉庫負荷,節省外網帶寬,加速Maven構建,自己部署構件等。
Nexus的特性:內存佔用小,REST API,支持代理倉庫、宿主倉庫、倉庫組,基於文件系統,圖形界面,支持搜索和權限控制。
兩種安裝包:
- 不包含Web容器的war包。
- 包含Jetty容器的Bundle包。解壓後得到nexus-webapp-1.7.2、sonatype-work。前者包括Nexus運行所需要的文件,如啓動腳本,依賴jar包,是運行必需的,相同版本的內容是一樣的。後者爲Nexus運行時動態創建的目錄,對於各實例是不一樣的(因爲不同的用戶在不同的環境下使用會有不同的配置和倉庫內容),所以備份也只需要備份這個目錄。
Windows啓動方式爲運行/bin/jsw/windows-x86-32/nexus.bat。
Linux啓動方式爲進入/bin/jsw/linux-x86-32/,運行$ . /nexus console。此時可以看到命令行輸出,使用Ctrl + C停止Nexus。此外還可以使用start/stop/status/restart,分別代表啓動/停止/查看狀態/重新啓動。
在/conf/plexus.properties中可找到application-port,修改端口號。
倉庫類型:
權限:Nexus基於權限做訪問控制,每一個資源都有相應的權限來控制。包括admin、deployment、anonymous,默認管理員爲admin/admin123,默認開發者爲deployment/deployment123。創建好倉庫後,還需要創建基於倉庫的增刪改查權限並進行分配。
Maven中使用私服:
<!-- 在settings.xml中配置Nexus倉庫 -->
<settings>
<profiles>
<profile>
<id>nexus</id>
<repositories>
<repository>
<id>nexus</id>
<name>Nexus</name>
<url>http://localhost:8081/nexus/content/groups/public/</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>nexus</id>
<name>Nexus</name>
<url>http://localhost:8081/nexus/content/groups/public/</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
<!-- 在settings.xml中配置 僅使用Nexus倉庫 -->
<settings>
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>http://localhost:8081/nexus/content/groups/public</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id></id>
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>nexus</activeProfile>
</activeProfiles>
</settings>
Maven部署構件至Nexus:
<!-- POM -->
<project>
<distributionManagement>
<repository>
<id>nexus-releases</id>
<name>Nexus Releases Repository</name>
<url>http://localhost:8081/nexus/content/repositories/releases/</url>
</repository>
<snapshotRepository>
<id>nexus-snapshots</id>
<name>Nexus Snapshots Repository</name>
<url>http://localhost:8081/nexus/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
</project>
<!-- settings -->
<settings>
<servers>
<server>
<id>nexus-releases</id>
<username>admin</username>
<password>admin123</password>
</server>
<server>
<id>nexus-snapshots</id>
<username>admin</username>
<password>admin123</password>
</server>
</servers>
</settings>
第十章:使用Maven進行測試
跳過,學習意義不大,對小公司來說時間成本過高,不如直接按照測試用例文檔進行自測,大公司在自測後會有單獨的測試環境和測試團隊來進行測試。
第十一章:使用Hudson進行持續繼承
持續集成(Continuous Integration):快速且高頻率地自動構建項目的所有源碼,併爲項目成員提供豐富的反饋信息。
持續集成示例:
集成的步驟:
- 持續編譯。與版本控制系統(如Git)集成,自動觸發編譯。
- 持續數據庫集成
- 持續測試
- 持續審查。與代碼檢查系統集成。
- 持續部署
- 持續反饋
集成的好處:儘早暴露問題、減少重複操作、簡化項目發佈、建立團隊信息。
第十二章:使用Maven構建Web應用
跳過,與主流的 Spring Boot 的項目骨架脫節太多。
第十三章:版本管理
跳過。
第十四章:靈活的構建
Maven屬性:內置屬性、POM屬性、自定義屬性、Settings屬性、Java系統屬性、環境變量熟悉。
自定義Maven屬性:變量定義在<properties>標籤裏,然後通過${}調用。
使用示例:將Spring的版本抽象出來統一管理;聚合項目中子模塊直接調用父的groupId和version。
profile示例(開發環境的數據庫配置)(可寫在POM、Settings):
<profiles>
<profile>
<id>dev</id>
<properties>
<db.driver>com.mysql.jdbc.Driver</db.driver>
<db.url>jdbc:mysql://localhost:3306/test</db.url>
<db.username>dev-username</db.username>
<db.password>dev-password</db.password>
</properties>
</profile>
</profiles>
激活profile:
- 命令行激活。在命令行尾部加上 -Pdev。
- Settings文件顯示激活。
<settings>
<activeProfiles>
<activeProfile>dev</activeProfile>
</activeProfiles>
</settings>
- 系統屬性激活。本質上和命令行激活一樣。
- 操作系統環境激活。(這個方法應該是最常用的,服務器和開發機OS一般都是不一樣的)
<profiles>
<profile>
<activation>
<os>
<name>Windows XP</name>
<family>Windows</family>
<arch>x86</arch>
<version>5.1.2600</version>
</os>
</activation>
</profile>
</profiles>
- 文件存在與否激活。和上面的類似,在<activation>標籤裏配置<file>標籤,<file>標籤裏配置<missing>標籤或<exists>標籤。
- 默認激活。和上面的類似,在<activation>標籤裏配置<activeByDefault>標籤,且值爲true。
命令行查看:通過$mvn help:all-profiles和$mvn help:active-profiles來查看所有profile和已激活的profile。
第十五章:生成項目站點
跳過,功能一般,用不到。
第十六章:m2eclipse
跳過,目前主流用IDEA。
第十七章:編寫Maven插件
跳過,前人編寫的插件能滿足幾乎100%的業務需求了,不用重複造輪子。
第十八章:Archetype
跳過,項目骨架不要標新立異,按照規範來,減少人員學習成本。