主頁 > 軟體工程 > 高效使用Java構建工具,Maven篇|云效工程師指北

高效使用Java構建工具,Maven篇|云效工程師指北

2022-04-02 08:43:15 軟體工程

大家好,我是胡曉宇,目前在云效主要負責Flow流水線編排、任務調度與執行引擎相關的作業,

作為一個有多年Java開發測驗工具鏈開發經驗的CRUD專家,使用過所有主流的Java構建工具,對于如何高效使用Java構建工具沉淀了一套方法,眾所周知,當前最主流的Java構建工具為Maven/Gradle/Bazel,針對每一個工具,我將分別從日常作業中常見的場景問題切入,例如依賴管理、構建加速、靈活開發、高效遷移等,針對性地介紹如何高效靈活地用好這3個工具,

image.png

Java構建工具的前世今生

在上古時代,Java的構建都在使用make,撰寫makefile來進行Java構建有非常多別扭與不便的地方,

緊接著Apache Ant誕生了,Ant可以靈活的定義清理編譯測驗打包等程序,但是由于沒有依賴管理的功能,以及需要撰寫復雜的xml,還是存在著諸多的不便,

隨后Apache Maven誕生了,Maven是一個依賴項管理和構建自動化工具,遵循著約定大于配置的規則,雖然也需要撰寫xml,但是對于復雜工程更加容易管理,有著標準化的工程結構,清晰的依賴管理,此外,由于Maven本質上是一個插件執行框架,也提供了一定的開放性的能力,我們可以通過Maven的插件開發,為構建構成創造一定的靈活性,

但是由于采用約定大于配置的方式,喪失了一定的靈活性,同時由于采用xml管理構建程序與依賴,隨著工程的膨脹,配置管理還是會帶來不小的復雜度,在這個背景下,集合了Ant與Maven各自優勢的Gradle誕生了,

Gradle也是一個集合了依賴管理與構建自動化的工具,首要的他不再使用XML而是基于Groovy的DSL來描述任務串聯起整個構建程序,同時也支持插件提供類似于Maven基于約定的構建,除了在構建依賴管理上的諸多優勢之外,Gradle在構建速度上也更具優勢,提供了強大的快取與增量構建的能力,

除了以上Java構建工具之外,Google在2015年開源了一款強大,但上手難度較大的分布式構建工具Bazel,具有多語言、跨平臺、可靠增量構建的特點,在構建上可以成倍提高構建速度,因為它只重新編譯需要重新編譯的檔案,Bazel也提供了分布式遠程構建和遠程構建快取兩種方式來幫助提升構建速度,

目前業內使用Ant的人已經比較少,主要都在用Maven、Gradle和Bazel,如何真正基于這三款工具的特點發揮出他們最大的效用,是這個系列文章要幫大家解決的問題,先從Maven說起,

優雅高效地用好Maven

當我們正在維護一個Maven工程時,關注以下三個問題,可以幫助我們更好的使用Maven,

● 如何優雅的管理依賴
● 如何加速我們的構建測驗程序
● 如何擴展我們自己的插件

優雅的依賴管理

在依賴管理中,有以下幾個實踐原則,可以幫助我們優雅高效的實作不同場景下的依賴管理,

● 在父模塊中使用dependencyManagement,配置依賴
● 在子模塊中使用dependencies,使用依賴
● 使用profiles,進行多環境管理

以我在日常開發中維護的一個標準的spring-boot多模塊Maven工程為例,

image.png

工程內各個module之間的依賴關系如下,通常這也是標準的 spring-boot restful api多模塊工程的結構,

image.png

便捷的依賴升級

通常我們在依賴升級的時候會遇到以下問題:

● 多個依賴關聯升級
● 多個模塊需要一起升級

在父模塊的pom.xml中,我們配置了基礎的spring-boot依賴,也配置了日志輸出需要的logback依賴,可以看出,我們遵循了以下的原則:

(1)在所有子模塊的父模塊中的pom中配置dependencyManagement,統一管理依賴版本,在子模塊中直接配置依賴,不用再糾纏于具體的版本,避免潛在的依賴版本沖突,
(2)把groupId相同的依賴,配置在一起,比如groupId為org.springframework.boot,我們配置在了一起,
(3)把groupId相同,但是需要一組依賴共同提供功能的artifactId,配置在一起,同時將版本號抽取成變數,便于后續一組功能共同的版本升級,比如spring-boot依賴的版本抽取成了spring-boot.version,

image.png
image.png

在子模塊build-engine-api的pom.xml中,由于在父pom中配置了 dependencyManagement中依賴的spring-boot相關依賴的版本,因此在子模塊的pom中,只需要在dependencies中直接宣告依賴,確保了依賴版本的一致性,

image.png

合理的依賴范圍

Maven依賴有依賴范圍(scope)的定義,compile/provieded/runtime/test/system/import,原則上,只按照實際情況配置依賴的范圍,在必要的階段,只引入必要的依賴,

90%的Java程式員應該都使用過org.projectlombok:lombok來簡化我們的代碼,其原理就是在編譯程序中將注解轉化為Java實作,因此該依賴的scope為provided,也就是編譯時需要,但在構建出最終產物時又需要被排除,

image.png

當你的代碼需要使用jdbc連接一個mysql資料庫,通常我們會希望針對標準 JDBC 抽象進行編碼,而不是直接錯誤的使用 MySQL driver實作,這個時候依賴的scope就需要設定為runtime,這意味著我們在編譯時無法使用該依賴,該依賴會被包含在最終的產物中,在程式最終執行時可以在classpath下找到它,

image.png

在子模塊dao中,我們有對sql進行測驗的場景,需要引入記憶體資料庫h2,

因此,我們將h2的scope設定為test,這樣我們在測驗編譯和執行時可以使用,同時避免其出現在最終的產物中,

image.png

更多關于scope的使用,可以參考官方幫助檔案,

多環境支持

舉個簡單的例子,當我們的服務在公有云部署時,我們使用了一個云上版本為8.0的MySQL,而當我們要進行專有云部署時,用戶提供一個自運維的版本為5.7的MySQL,因此,我們在不同的環境中使用不同的 mysql:mysql-connector-java 版本,

類似的,在專案實際的開發程序中,我們經常會面臨同一套代碼,在多套環境中部署,存在部分依賴不一致的情況,

image.png

關于profiles的更多用法,可以參考官方幫助檔案

依賴糾錯

如果你已經在父pom中使用dependencyManagement來鎖定依賴版本,大概率的,你幾乎很少會碰到依賴沖突的情況,

但是當你還是意外的看到了NoSuchMethodError,ClassNotFoundException 這兩個例外的時候,有以下兩個方法可以快速的幫你糾錯,

(1)通過依賴分析找到沖突的依賴

image.png

(2)通過添加stdout代碼找到沖突的類實際是從哪個依賴中查找的

image.png

通過具體的路徑中對應的版本資訊,找到對應的版本并校正,

image.png

當然這個方法也可以糾出一些依賴被錯誤的加載到classpath下,非工程本身依賴配置引起的沖突,

測驗構建程序加速

作為一個開發者,總會希望我們的工程無論在什么情況下,執行的又快又穩,那么在Maven的使用程序中,需要遵循以下原則,

● 盡可能復用快取
● 盡可能的并行構建或測驗

依賴下載加速

通常情況下,根據Maven組態檔 ${user.home}/.m2/settings.xml 中的配置,默認情況下是快取在${user.home}/.m2/repository/,

image.png

通常在構建程序中,依賴的下載往往會成為比較耗時的部分,但是通過一些簡單的設定,我們可以有效的減少依賴的下載與更新,

● 優化updatePolicy設定
updatePolicy指定了嘗試更新的頻率,Maven 會將本地 POM 的時間戳(存盤在存盤庫的 maven-metadata 檔案中)與遠程進行比較,選項包括:always(總是)、daily(每天,默認值)、interval:X(其中 X 是以分鐘為單位的整數)、never(從不),

image.png

● 使用離線構建
除此之外,如果構建環境已經存在快取,可以使用Maven的offline模式進行構建,避免依賴或插件的下載更新,

直觀的,日志中將不會出現類似如下Downloading相關的資訊,

image.png

構建程序加速

在默認情況下,Maven構建的程序并不會充分的使用你的硬體的全部能力,他會順序的構建你的maven工程的每一個模塊,這個時候,如果可以使用并行構建,那么將有機會提升構建速度,

image.png

以上是并行構建的兩個命令,可以根據實際的cpu情況來選擇對應的命令,但是如果你發現構建時間并沒有得到減少,那么你的maven模塊間可能存在類似的依賴,模塊之間只是一個簡單的傳遞,

image.png

那么并行構建對你來說并不適用,如果你的模塊間依賴關系存在并行的可能,那么使用上述命令進行構建,才能使并行構建發揮效果,

image.png

測驗程序加速

當我們嘗試加速maven工程測驗用例的部分,那么就不得不提到一個插件,maven-surefire-plugin,

當你在執行mvn test的時候,默認情況下就是surefire插件在作業,如果我們想在測驗中使用并行的能力,可以作如下配置,

image.png

但是需要注意不恰當的使用并行能力進行測驗,反而可能帶來副作用,比如當parallel配置為methods,但是由于某些原因測驗用例的執行之間存在順序要求,反而會出現因為用例方法并行執行,導致用例失敗,因此也倒逼我們,如果想獲得更快的測驗速度,case的撰寫也需要獨立且高效,

更多關于surefire插件的使用,可以參考這篇檔案,

Maven插件開發

maven本質上是一個插件執行框架,所有的執行程序,都是由一個一個插件獨立完成的,關于maven的核心插件可以參考這篇檔案,

maven默認為我們提供的這些插件比如maven-install-plugin/mvn-surefire-plugin/mvn-deploy-plugin外,還有一些三方提供的插件,單測覆寫率插件mvn-jacoco-plugin,生成api檔案的swagger-maven-plugin等等,

在日常作業的程序中,我碰到了這樣一個問題:有個存在明顯問題的sql被發布到了預發布環境,同時由于預發與生產使用的是同一個db實體,由于sql的性能問題,影響了線上,

除了通過必要的code review準入,來避免類似的問題,更簡單的,我們可以自己動手實作一個代碼中sql掃描的插件,讓代碼在CI時直接失敗掉,自動化的避免此類問題的發生,于是我們開發了一個maven插件,使用方法和效果如下:

在工程中引入我們開發并部署好的插件com.aliyun.yunxiao:mybatis-sql-scan,

image.png

執行以下命令,或其他包含validate階段執行的命令,

image.png

我們將會在日志中看到如下插件執行的資訊

image.png

在掃描出缺陷時,build失敗,并會在日志中出現對應的資訊:

在GlobalLockMapper.java這個檔案中,我們有一條全表掃描的sql陳述句可能存在風險,

image.png

同時build失敗,

image.png

接下來我會從如何開發這個例外sql掃描的maven插件入手,幫助大家了解插件開發的程序,

1、創建工程

image.png

生成的sample工程如下,

image.png

其中MyMojo.java定義了插件的入口實作,

此外在根pom.xml中可以看到,

● packaging為“maven-plugin”,
● 依賴配置中,依賴了一些插件開發的基礎二方庫,
● 插件節點下,依賴了maven-plugin-plugin協助我們完成插件的構建,

image.png
image.png

2、Mojo實作

在開始實作我們的Mojo之前,我們需要做如下分析:

● 插件在maven的哪個生命周期執行
● 插件在執行時需要哪些入口引數
● 插件執行完成后怎么退出

由于我們要實作的插件是要做mybatis annotation掃描比如 @Update/@Select,判斷是否有例外的sql,比如是否存在全表掃描的sql,是否存在全表更新的sql等,對于此種場景下,

● 由于需要掃描特定的原始碼,需要知道工程原始碼的所在目錄,以及掃描哪些檔案
● 插件掃描出例外時,只要報錯即可,不用產出任何報告
● 希望在后續執行mvn validate時觸發掃描

那么預期中的插件是這樣的,

image.png

那么,

● @Mojo(name = "check") 定義了goal
● @Parameter
○ @Parameter(defaultValue = "https://www.cnblogs.com/yyds114/p/${project}", readonly = true) 引數系結了工程的根目錄 ,project.getCompileSourceRoots()便可以獲取到源代碼的根路徑
○ 我們定義了mapperFiles,用來負責掃描哪些檔案的通配,excludeFiles用來負責排除哪些檔案
● execute()
○ 有了以上的基礎,在execute方法中我們便可以實作對應的邏輯,當掃描結出例外的sql時,拋出MojoFailureException例外,插件便會失敗終止,

image.png

以上,我們便完成了一個插件的基本能力的開發,

3、插件的打包與上傳

插件開發完成后,我們可以通過配置distributionManagement,然后執行mvn deploy,完成插件的構建與發布,

image.png

希望通過我的介紹,能夠幫助大家更好的使用maven,下一篇我們講Gradle,歡迎持續關注我們,

點擊下方鏈接,即可免費體驗云效流水線Flow,

https://www.aliyun.com/product/yunxiao/flow?channel=yy_practice

lQLPDhtDba1KT2_NBDjNB4CwgwE-eOLUK_gCPyXeUECTAA_1920_1080.png

轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/454665.html

標籤:其他

上一篇:在一個目錄中運行15hdf5來計算一個函式,但再次重復同一個表

下一篇:高效使用Java構建工具,Maven篇|云效工程師指北

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • Git本地庫既關聯GitHub又關聯Gitee

    創建代碼倉庫 使用gitee舉例(github和gitee差不多) 1.在gitee右上角點擊+,選擇新建倉庫 ? 2.選擇填寫倉庫資訊,然后進行創建 ? 3.服務端已經準備好了,本地開始作準備 (1)Git 全域設定 git config --global user.name "成鈺" git c ......

    uj5u.com 2020-09-10 05:04:14 more
  • CODING DevOps 代碼質量實戰系列第二課,相約周三

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。**《DevOps 代碼質量實戰(PHP 版)》**為 CODING DevOps 代碼質量實戰系列的第二課,同時也是本系列的 PHP ......

    uj5u.com 2020-09-10 05:07:43 more
  • 推薦Scrum書籍

    推薦Scrum書籍 直接上干貨,推薦書籍清單如下(推薦有順序的哦) Scrum指南 Scrum精髓 Scrum敏捷軟體開發 Scrum捷徑 硝煙中的Scrum和XP : 我們如何實施Scrum 敏捷軟體開發:Scrum實戰指南 Scrum要素 大規模Scrum:大規模敏捷組織的設計 用戶故事地圖 用 ......

    uj5u.com 2020-09-10 05:07:45 more
  • CODING DevOps 代碼質量實戰系列最后一課,周四發車

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。 **《DevOps 代碼質量實戰(Java 版)》**為 CODING DevOps 代碼質量實戰系列的最后一課,同時也是本系列的 ......

    uj5u.com 2020-09-10 05:07:52 more
  • 敏捷軟體工程實踐書籍

    Scrum轉型想要做好,第一步先了解并真正落實Scrum,那么我推薦的Scrum書籍是要看懂并實踐的。第二步是團隊的工程實踐要做扎實。 下面推薦工程實踐書單: 重構:改善既有代碼的設計 決議極限編程 : 擁抱變化 代碼整潔代碼 程式員的職業素養 修改代碼的藝術 撰寫可讀代碼的藝術 測驗驅動開發 : ......

    uj5u.com 2020-09-10 05:07:55 more
  • Jenkins+svn+nginx實作windows環境自動部署vue前端專案

    前面文章介紹了Jenkins+svn+tomcat實作自動化部署,現在終于有空抽時間出來寫下Jenkins+svn+nginx實作自動部署vue前端專案。 jenkins的安裝和配置已經在前面文章進行介紹,下面介紹實作vue前端專案需要進行的哪些額外的步驟。 注意:在安裝jenkins和nginx的 ......

    uj5u.com 2020-09-10 05:08:49 more
  • CODING DevOps 微服務專案實戰系列第一課,明天等你

    CODING DevOps 微服務專案實戰系列第一課**《DevOps 微服務專案實戰:DevOps 初體驗》**將由 CODING DevOps 開發工程師 王寬老師 向大家介紹 DevOps 的基本理念,并探討為什么現代開發活動需要 DevOps,同時將以 eShopOnContainers 項 ......

    uj5u.com 2020-09-10 05:09:14 more
  • CODING DevOps 微服務專案實戰系列第二課來啦!

    近年來,工程專案的結構越來越復雜,需要接入合適的持續集成流水線形式,才能滿足更多變的需求,那么如何優雅地使用 CI 能力提升生產效率呢?CODING DevOps 微服務專案實戰系列第二課 《DevOps 微服務專案實戰:CI 進階用法》 將由 CODING DevOps 全堆疊工程師 何晨哲老師 向 ......

    uj5u.com 2020-09-10 05:09:33 more
  • CODING DevOps 微服務專案實戰系列最后一課,周四開講!

    隨著軟體工程越來越復雜化,如何在 Kubernetes 集群進行灰度發布成為了生產部署的”必修課“,而如何實作安全可控、自動化的灰度發布也成為了持續部署重點關注的問題。CODING DevOps 微服務專案實戰系列最后一課:**《DevOps 微服務專案實戰:基于 Nginx-ingress 的自動 ......

    uj5u.com 2020-09-10 05:10:00 more
  • CODING 儀表盤功能正式推出,實作作業資料可視化!

    CODING 儀表盤功能現已正式推出!該功能旨在用一張張統計卡片的形式,統計并展示使用 CODING 中所產生的資料。這意味著無需額外的設定,就可以收集歸納寶貴的作業資料并予之量化分析。這些海量的資料皆會以圖表或串列的方式躍然紙上,方便團隊成員隨時查看各專案的進度、狀態和指標,云端協作迎來真正意義上 ......

    uj5u.com 2020-09-10 05:11:01 more
最新发布
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:41:12 more
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:35:34 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:05:44 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:00:18 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:20:31 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:55 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:18:51 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:00 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:17:55 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:12:06 more