我在工做中是這樣使用Maven

前言

上次說到我在工做中是這樣使用Git,已是1個月前的故事了,時間啊,就這樣慢慢流逝了。java

此次來講說maven這玩意,一樣仍是那句話,maven對我而言只是工具,一些常規操做已經足夠了,有空有興趣纔會去深刻研究它。接下來會記錄下本身使用maven時須要注意理解的地方,至於那些基本概念和環境配置的問題,相信你們都懂。linux

倉庫

maven倉庫可分爲本地倉庫遠程倉庫web

若是公司本身有搭建maven私服,那麼還能夠細分爲本地倉庫私服倉庫(內網)中央倉庫(外網)spring

私服是指公司內網搭建的maven倉庫,可供公司內部人員使用。數據庫

pom.xml裏依賴jar包的尋找流程:apache

  1. 本地倉庫找,找到直接用,不須要聯網。
  2. 本地找不到, 私服倉庫找,找到就下載到本地,以供下次直接使用。
  3. 私服找不到,會直接去 中央倉庫找,而後下載到私服、本地,以供下次直接使用。

沒私服的話,本地倉庫找不到就直接去中央倉庫找。json

構建過程

maven構建過程的各個環節,表明maven工做的某個階段api

  1. 清理:將之前編譯獲得的 舊的class字節碼文件刪除,爲下一次編譯作準備。
  2. 編譯:將Java源程序 編譯成class字節碼
  3. 測試:自動測試, 自動調用junit程序
  4. 報告:測試程序執行的結果。
  5. 打包:動態Web工程 打war包,java工程 打jar包
  6. 安裝:將打包獲得的文件 複製到倉庫中指定位置
  7. 發佈: 拷貝最終的工程包到遠程倉庫,以供其餘開發人員使用。

maven實際工做時,順序不必定從上到下。幾個階段是重要階段,並非maven的所有階段。具體執行什麼階段,執行順序是啥,依賴於它的生命週期。tomcat

有些文章會說到最後一個構建階段:部署->將動態Web工程生成的war包複製到Servlet容器的指定目錄下,使其運行。 這須要在tomcat這種servlet容器配置點什麼,而後再執行maven相關命令,war包就會自動部署到容器下。不過我如今開發基本都是在SpringBoot環境下,war包部署就不存在了。有興趣再去熟悉熟悉。服務器

生命週期

三套相互獨立的生命週期,互不影響,定義了構建環節的執行順序

  1. clean生命週期:構建以前進行一些 清理工做
  2. default生命週期: 經常使用且核心,包括編譯、測試、打包、安裝、發佈等
  3. site生命週期:生成項目報告、站點。發佈站點。(我沒怎麼用過....)

依賴上述的構建過程和生命週期,maven執行任何一個階段的時候,它前面的全部階段都會執行

例如咱們執行 mvn install 的時候,代碼會被編譯,測試,打包。但不會clean(清理),由於install和clean是在不一樣的生命週期裏,但咱們能夠結合使用,如:mvn clean install

idea內置maven界面也說明這一點,點擊生命週期的某一個階段,maven會把前面到此階段都執行下,不信你能夠試試。

maven命令

除了經過idea的界面操做maven,咱們也能夠手打命令,否則在linux系統上你怎麼搞?

  • 清理 mvn clean
  • 編譯 mvn compile
  • 測試 mvn test
  • 打包 mvn package
  • 安裝 mvn install
  • 發佈 mvn deploy

執行maven構建命令,必須在pom.xml所在的目錄

根據maven生命週期,當你執行mvn install時, compile、test、package、intall會依次執行,mvn deploy同理。

實際開發中,我都是直接敲命令編譯打包安裝,用得最多的是

mvn clean install -Dmaven.test.skip=true -U

加上clean是先把文件清理乾淨,100%確保install後是最新修改的文件。

若是當前項目並不須要被任何其餘項目依賴,就不必install了,執行mvn clean package便可

mvn命令支持帶參數

  • -U :該參數能強制讓Maven檢查全部SNAPSHOT依賴更新,確保集成基於最新的狀態。
  • -Dmaven.test.skip=true :不執行測試用例,也不編譯測試用例類。
  • -DskipTests :不執行測試用例,但編譯測試用例類生成相應的class文件至target/test-classes下。
  • -P : 多環境打包(後面會說)

插件

maven倉庫除了保存jar包,還有插件。核心程序僅定義了抽象的生命週期,具體工做仍是得由特定的插件來完成。

通常我使用maven-compiler-plugin 插件來編譯,定義的jdk版本必定要跟你開發使用的jdk版本一致,否則後續打包會出錯等各類奇怪問題。

pom.xml的build節點裏

<build>
 <plugins>  <plugin>  <groupId>org.apache.maven.plugins</groupId>  <artifactId>maven-compiler-plugin</artifactId>  <version>3.1</version>  <configuration>  <source>1.8</source>  <target>1.8</target>  <encoding>UTF-8</encoding>  </configuration>  </plugin>  </plugins> </build> 複製代碼

依賴範圍

標識jar包能被管理的範圍。

<dependency>
 <groupId>org.springframework</groupId>  <artifactId>spring-context</artifactId>  <version>5.1.3</version>  <scope>compile</scope> </dependency> 複製代碼
  • compile:依賴項目參與編譯、測試、部署運行

  • test:僅參與測試,包括測試代碼的編譯、運行

  • provided:能夠參與編譯、測試,但打包不會引入


一張表格來總結

compile test provided
主程序 ×
測試程序
參與部署 × ×

上述3個比較常見,還有另外3個不常見的
  • runtime:無需參與編譯、後期測試和運行週期需參與,通常用於數據庫驅動jar包
  • system:jar包從本地次磁盤路徑拿,不用在maven倉庫,通常加個systemPath節點表示具體路徑
<dependency>
 <groupId>org.springframework</groupId>  <artifactId>spring-context</artifactId>  <version>5.1.3</version>  <scope>system</scope>  <systemPath>../xx/xx.jar</systemPath> </dependency> 複製代碼
  • import:導入另外一jar包的東西,僅支持在<dependencyManagement>中定義(後續有例子)

注意:非compile的依賴不能傳遞!

打包方式

packaging節點裏

<groupId>com.goku</groupId>
<artifactId>goku-manage</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> 複製代碼
  • pom:依賴文件打包, 打出來能夠做爲其餘項目的maven依賴,子工程繼承父工程,子工程可直接使用父工程的配置,通常用在聚合工程來作jar包的版本控制。
  • jar:普通項目打包,開發時要引用通用類,打成jar包便於存放管理。SpringBoot內置tomcat,打成jar可直接運行。
  • war:web項目打包,打成war包部署到服務器。

聚合與繼承

聚合工程裏有多個pom.xml

父工程經過modules聚合子工程,該工程執行maven命令時,2個子工程也會執行

<modules>
 <module>goku-user</module>  <module>goku-order</module> </modules> 複製代碼

子工程經過parent標籤繼承父工程,可直接引用父工程的配置項

<parent>
 <groupId>com.goku</groupId>  <artifactId>goku-manage</artifactId>  <version>1.0-SNAPSHOT</version> </parent> 複製代碼

至於聚合模塊的好處有不少,真真切切讓我感覺到的有其二

  1. 依賴包劃分合理,職責結構清晰,不存在一個龐大的pom.xml。
  2. 內部代碼改動後只須要編譯當前工程,耗時減小。特別適合分佈式項目。

統一版本號

聚合工程裏,版本號能夠統一配置,統一管理。同個公司的不一樣項目,全部依賴包版本最好相同。

有些公司會單獨建一個工程,只用來統一版本號,打包成pom形式,給公司內部各個項目繼承。


頂層父工程的pom文件裏的properties節點

<properties>
 <java.version>1.8</java.version>  <plugin.jdk.version>1.8</plugin.jdk.version>  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  <spring-boot.version>2.1.3.RELEASE</spring-boot.version>  <fasterjson.version>1.2.12</fasterjson.version> </properties> 複製代碼

dependency的vesion引用配置好的版本號

<dependency>
 <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-web</artifactId>  <version>${spring-boot.version}</version> </dependency> 複製代碼

dependencyManagement統一管理版本

請注意<scope>import</scope>

<dependencyManagement>
 <dependencies>  <dependency>  <!-- Import dependency management from Spring Boot -->  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-dependencies</artifactId>  <version>2.0.0.RELEASE</version>  <type>pom</type>  <!--導入spring-boot-dependencies裏的配置,必定程度上解決了單繼承問題。-->  <scope>import</scope>  </dependency>  <dependency>  <groupId>org.slf4j</groupId>  <artifactId>slf4j-api</artifactId>  <version>${slf4j.version}</version>  </dependency>  <dependency>  <groupId>com.alibaba</groupId>  <artifactId>fastjson</artifactId>  <version>${fasterjson.version}</version>  </dependency>  </dependencies>  </dependencyManagement> 複製代碼

說明:

  1. dependencyManagement只是聲明依賴,不會引入依賴。
  2. 子模塊不會繼承父模塊中dependencyManagement全部預約義的depandency,若想使用還需引入須要的依賴,只不過不須要加version節點了。
  3. 聽說在父模塊中嚴禁直接使用depandencys預約義依賴,應該作到按需引入。

多環境打包

項目打包時區分環境,其實是根據不一樣環境生成不一樣的配置文件。

通常區分本地、開發/測試、線上。

pom.xml裏的build和profiles(如下配置僅針對SpringBoot的yml文件)

<build>
 <!-- 打包後文件名稱:項目名-環境-版本 -->  <finalName>${project.artifactId}</finalName>  <resources>  <resource>  <directory>src/main/resources</directory>  <!-- 開啓過濾替換功能-->  <filtering>true</filtering>  <includes>  <!-- 項目打包完成的包中只包含當前環境文件 -->  <include>application.yml</include>  <include>application-${profileActive}.yml</include>  <include>**/*.xml</include>  <include>**/*.properties</include>  </includes>  </resource>  </resources> </build>   <!-- 多環境配置方案 --> <profiles>  <profile>  <id>local</id>  <properties>  <profileActive>local</profileActive>  </properties>  <activation>  <!-- 默認狀況下使用本地開發配置 如 打包時不包含 -p 參數-->  <activeByDefault>true</activeByDefault>  </activation>  </profile>  <!-- 打包命令package -P test -->  <profile>  <id>test</id>  <properties>  <profileActive>test</profileActive>  </properties>  </profile>  <!-- 打包命令package -P prod -->  <profile>  <id>prod</id>  <properties>  <profileActive>prod</profileActive>  </properties>  </profile> </profiles> 複製代碼

maven命令帶參數-P,如:mvn clean install -P test

項目打包後只保留application.yml、ymlapplication-test.yml

application.yml裏的@profileActive@也會被替換成test

最終打包生成的文件

setting.xml

localRepository

指定本地倉庫地址,不配置就放在默認路徑${user.home}/.m2/repository

<localRepository>D:\develop\maven\Repmaven</localRepository>
複製代碼

server

公司搭建了maven私服,上傳下載須要認證,就須要配置。

NOTE: You should either specify username/password OR privateKey/passphrase, since these pairings are used together.

可配置帳號密碼 或 私鑰形式,支持多個server

<servers>
 <server>  <!--id須要與repository或mirror中的id相對應-->  <id>server01</id>  <username>admin</username>  <password>SwaDmin159</password>  </server>  <server>  <id>server02</id>  <privateKey>/xxx/.ssh/id_dsa</privateKey>  <passphrase>some_passphrase</passphrase>  <filePermissions>664</filePermissions>  <directoryPermissions>775</directoryPermissions>  <configuration></configuration>  </server> </servers> 複製代碼

mirror

倉庫鏡像,中央倉庫的代理,若是配置了鏡像,就直接去鏡像中下載依賴。它至關於一個攔截器,攔截maven對默認中央倉庫的請求,把請求裏的遠程倉庫地址,重定向到mirror裏配置的地址。

<mirrors>
 <mirror>  <id>nexus-aliyun</id>  <mirrorOf>central</mirrorOf>  <name>Nexus aliyun</name>  <url>http://maven.aliyun.com/nexus/content/groups/public</url>  </mirror>  </mirrors> 複製代碼

profile and activeProfiles

全部項目使用私服倉庫,可在setting.xml配置,profile節點配置repositories,最後再激活profile。

固然,私服裏不僅一個倉庫,可配置多個repository。

<profile>
 <repositories>  <repository>  <!-- id須要與私服裏倉庫的id對應 -->  <id>public</id>  <name>public</name>  <url>http://xxx.com/nexus/content/groups/public/</url>  <layout>default</layout>  </repository>  </repositories> </profile>  <activeProfiles>  <activeProfile>public</activeProfile> </activeProfiles> 複製代碼

若只想針對某個項目,則在當前項目的pom.xml配置私服,repositories節點下配置便可

<repositories>
 <repository>  <!-- id須要與私服裏倉庫的id對應 -->  <id>public</id>  <name>public</name>  <url>http://xxx.com/nexus/content/groups/public/</url>  <releases>  <enabled>true</enabled>  </releases>  <snapshots>  <enabled>true</enabled>  </snapshots>  </repository> </repositories> 複製代碼

distributionManagement

有時咱們本身開發的模塊須要被其餘部門的開發人員使用,就須要發佈到私服。

執行mvn deploy前,需配置distributionManagement。

快照版本跟發佈版本分別存儲到不一樣倉庫地址。

<distributionManagement>
 <repository>  <id>release</id>  <name>Project Release</name>  <url>http://xxx.com/nexus/content/groups/release/</url>  </repository>  <snapshotRepository>  <id>snapshots</id>  <name>Project SNAPSHOTS</name>  <url>http://xxx.com/nexus/content/groups/snapshot/</url>  </snapshotRepository> </distributionManagement> 複製代碼

快照版本vs發佈版本

maven會根據jar包的版本號(version節點)是否帶有-SNAPSHOT來判斷是快照版本仍是正式版本。沒有SNAPSHOT都認爲是快照版本。

快照版本 :1.0.0-SNAPSHOT

發佈版本 :1.5.3.RELEASE

若是是快照版本,在mvn deploy時會自動發佈到快照版本庫中,覆蓋老的快照版本,後面使用快照版本模塊時,在不更改版本號的狀況下,直接編譯打包時,maven會自動從遠程服務器上下載最新的快照版本。

若是是正式發佈版本,在mvn deploy時會自動發佈到正式版本庫中,後面使用正式版本的模塊,在不更改版本號的狀況下,編譯打包時若是本地已經存在該版本的模塊則不會主動去遠程服務器上下載。

這個也容易理解,快照版本通常定義爲不穩定版本,須要實時更新。

總結

maven使用,放大可看
maven使用,放大可看

最後

若以爲此文對你有幫助,麻煩點個小贊,這對我將是最大的鼓勵!

微信搜悟空Java或掃碼關注悟空公衆號,一塊兒學習一塊兒進步!

相關文章
相關標籤/搜索