玩轉IDEA專案結構Project Structure,打Jar包、模組/依賴管理全搞定

YourBatman發表於2021-02-02

前言

你好,我是A哥(YourBatman)。

如何給Module模組單獨增加依賴?
如何知道哪些Module模組用了Spring框架,哪些是web工程?
IDEA如何打Jar包?打War包?

熟練的正確使用IntelliJ IDEA,是一個“高手”該有的樣子,因為那是你的門面上篇文章 重點介紹了IDEA裡最為重要的兩個概念:Project專案和Module模組。相信你看完後再也不會把IDEA的Project比作Eclipse的Workspace,並且對IDEA有了一份更深的瞭解。

本文繼續理解IDEA對專案、模組的管理。管理專案是一個IDE的基本功能,但往往最基礎的是最重要的更是最容易被忽略的。因此本文是你更好去理解IDEA管理maven結構、gradle結構、Spring Boot專案結構的基礎,萬丈高樓平地起,它就是這個地基。上層結構再怎麼繁繁多變,殊途同歸最終都由Project Structure來體現,從而給開發者以幾近相同的編碼體驗。

本文提綱

版本約定

  • IntelliJ IDEA:2020.3.1

正文

Project Structure是一個你開發過程中偶爾/經常會開啟,但卻很少用心留意的視窗。不同於一般設定視窗,它和專案的緊密度非常的高且有一定理解難度,若設定不當專案可能無法執行甚至無法編碼(比如編譯報錯、jar包找不著等),為此我做件一般人都不願意做的事,對它進行詳解,相信做難事必有所得。

本文基於上文已搭建好的hello專案案例,繼續研究其專案結構Project Structure的管理。從結構檢視,到修改定製,那麼問題來了,如何開啟一個Project專案的結構頁呢?

如何開啟Project Structure?

看似一個簡單的操作,裡面其實蘊藏著你對IDEA Project和Module的理解,否則勢必不知從哪下手。據瞭解,也許你是多年的程式設計師,也未必知道從哪下手。

按照一般思維,會滑鼠選中hello,然後右鍵:


但對不起,右鍵選單裡並無Project Structure選項。Project Structure顧名思義,是針對Project維度的結構視窗,而你滑鼠選中的hello只是個module,所以自然彈出的是對此module的操作選單嘍,而非Project的。也許你可能會講:我點選了Open Module Settings也開啟了Project Structure視窗呀,是的效果上你可能是開啟了但道理並非如此,而僅僅是因為把它倆放在了一起(同一視窗)而已。

說明:理解IDEA的Project和Module兩大概念,是對IDEA進行一切操作的基礎。前文已非常詳細(可能是全網最全)的介紹了它倆,可花幾分鐘前往學習。點這裡電梯直達

三種開啟方式

要開啟一個Project的結構展示視窗,至少有如下三種辦法,本文都例舉給你。

  1. 頂部選單File -> Project Structure

  1. 點選右上角的快捷按鈕

  1. 快捷鍵方式(推薦)

這是我本人最喜歡的方式,至於快捷鍵是哪個就看你是如何設定的嘍,我的快捷鍵是ctrl + shift + alt + s。

囉嗦一句:建議你操作IDEA多用快捷鍵,那會大大提高編碼的效率,並且看起來像高手。基本上記住50個左右快捷鍵就夠用了,長期以往成了肌肉記憶後這就是你的核心競爭力之一了


開啟hello專案的結構頁如下圖所示:

解釋:為何不需要滑鼠選中專案?

對於這個動作,敏感的你是否有發現:開啟專案結構並不需要滑鼠選中任何東西(快捷鍵隨意使用),也就是說滑鼠失焦狀態都沒問題,何解呢?

回答這個問題並不難,前提是你已經對IDEA的Project概念爛熟於胸。一個Project對應一個視窗,它們是嚴格1:1的關係。換句話講,當前視窗就代表著Project,因此操作本視窗頂部選單欄就肯定是作用在該Project上,又何須專門選中什麼呢?再者,Project只是個邏輯概念,你想選都沒得選中的,所以把視窗當作它就好。有沒有覺得,這和Java中的this關鍵字呼叫特別像?

最後,這個問題的答案是:只要滑鼠還在IDEA視窗內(該視窗是活躍視窗),那麼對Project就永遠就是“選中”狀態。

Project Structure專案結構剖析

專案結構視窗已開啟,那接下來重點來嘍。可以看到它左邊的“選單欄”,共分為三個part:

  • Project Settings:專案設定(最重要),本文詳解
  • Platform Settings:平臺設定,也叫全域性設定。用於管理SDK們(如JDK、Kotlin的SDK等)、全域性庫。
    • 一般來講,全域性的JDK都會配置在此處,比如我因為經常要做多版本嘗試,就管理了多個JDK版本

  • Problems:問題。一般專案出現了問題都會在此體現(如依賴不一致問題等等),總之問題數量一致讓它是0是最優的

其中Project Settings裡面的每個標籤頁是最常用,最關心的。下面就對它的每個tab頁作出解釋和使用說明。

Project頁情況

此視窗可以看到Project本身的基礎資訊。如:名稱、SDK版本、語言等級等等,比較簡單。

對於此頁面的元素,多囉嗦幾句:

  1. 為何是SDK版本而不是JDK版本?答:因為IntelliJ IDEA是JVM平臺IDEA,不僅僅支援Java還有其它語言如Kotlin,所以寫成SDK更抽象
  2. 為何指定了SDK還要指定語言等級?答:因為SDK版本並不直接決定語言等級。如你用的JDK 11,但依舊可以把語言等級調為8來進行編譯/執行
    1. 這是整合開發環境的優勢所在,輕鬆對多環境進行定製化支援
  3. SDK和語言等級Project都可指定,作為全域性預設
    1. 這些配置Module預設整合,但可自行修改自己的。比如module 1使用Java 5編譯,module 2使用Java 11編譯,這是允許的

Module頁情況

Module頁可謂是重點中的重點,甚至是最重要。畢竟Module作為實際存在形式,所有的原始碼、配置、依賴等都在這裡,因此大有可學呀。

值得注意:Tests測試包裡面的是可以訪問Sources原始碼的,但反過來不行。

每個模組都能獨立管理著自己的依賴,這種關係在模組自己的.iml檔案中記錄著。

知識點:

  1. Project建立時預設會建立一個同名的Module模組
  2. Module預設沿用Project的SDK、語言等級等設定,當然也可自己指定
  3. 每個Module可自行管理依賴,可以是二方庫、三方庫......
  4. 本模組的依賴情況預設儲存在專案的{moduleName}.iml檔案裡

新增依賴

既然Module可以自行管理依賴,那麼如何給該模組新增依賴呢?

舉個例子,現在需要向hello模組增加一個commons-io jar包依賴,可以點選Dependencies標籤頁左下角的+號,選擇Library:

然後選擇,如果沒有就選擇New Libarary...建立一個唄(有就直接用就成):

下面分別演示選擇Java和選擇From Maven兩種不同庫的方式:

新建Java依賴庫

New Library新建選單選項中選擇Java選項:

這種方式簡單的講:從你本機裡選擇一個jar(或者一個目錄裡面包含jar、文件)就成。優點是非常輕便,不依賴網路,缺點是這些jar必須是你本機已實際存在的。

新建Maven依賴庫

New Library新建選單選項中選擇From Maven選項:

輸入GAV(或者關鍵字查詢)就能定位到jar,此種方式使用起來其實非常方便,畢竟maven非常好用嘛。缺點自然就是一般情況下需要都需要依賴於網路嘍,除非你本地倉庫已存在對應的jar。


通過這兩種方式各執行一次新增新的依賴完成後,再看hello模組的依賴情況,效果如圖:

既然依賴變化了,自然而然的也會體現在hello.iml檔案裡嘍,來看看:

依賴新增進來,原始碼裡就可以正常使用啦:

依賴作用範圍

在New Library建立依賴的時候,不管用哪種方式選中後,它都會彈出這個視窗讓你選擇此依賴的作用範圍

  • Module Library:模組級別,只能本模組使用,別的模組看都看不見
  • Project Library(預設選中):專案級別,該專案下所有的模組均能看見和選中使用
  • Global Library:全域性級別,任何專案均可看見和使用

在本例中commons-io是模組級別,commons-lang3是專案級別。因此hello-client模組新增依賴時也是能夠看到commons-lang3這個依賴的(但看不見commons-io):

Libraries頁情況

當某Library是所有/大部分模組都需要的依賴時,就可以上升為Project級別的依賴,抽取到Libraries標籤頁來統一管理。如圖,因為上面步驟建立的commons-lang3是專案級別的,所以也會出現在這裡。

至於如何建立/新增Project級別的依賴,這裡就不用再贅述了吧,上面【新增依賴】章節已講得很明白。唯一區別在該頁面選好後不用再選擇Library的作用範圍了(因為就是Project級別的嘛),取而代之的是讓你選擇作用的模組:

當然嘍,你也可以一個都不選(點選cancle),那麼該jar只是被建立了,而不作用於任何module模組。

說明:對於一個多模組的Project來講,建議專案使用的所有Jar都放在這裡統一管理,模組要使用時直接按需choose就成,而不需要自己再單獨add,方便統一管理

Facets頁情況

Facets可理解為用於配置Project專案的框架區,它能看到專案的每個Module模組使用的框架、語言等情況,並且還可以對它們進行配置。

比如Spring框架,如果某個模組使用了它就可以來這裡統一配置。優點是你會發現藉助IDEA強大的功能它都給你想好了哪些地方可配置,你可以更改,讓你實現配置介面化。除了Spring,其它框架如Hibernate也是如此~

目前支援的Facets(語言/框架)型別有:

模組對應的Facets IDEA會自動Detection探測,若沒有你也可以手動新增。

為了更形象的描述此tab頁的作用,這裡搬一個我自己生產專案來看看實際效果:

說明:不同的Facet對應的最右端視窗內容配置項是不一樣的。

通過此視窗,可以看到你當前Project專案,哪些模組使用了Spring框架,哪些是web專案,一目瞭然。它有個非常大的作用就是站在Project的視角對每個模組進行整體把控,比如若你發現有個模組不需要是web專案(並不需要對外提供服務介面),那鐵定就是多引包了或者職責不清晰導致的,就可立馬針對性解決,消除隱患。

在實際工作中我自己比較頻繁的使用這個功能,用於對模組性質的定位,比如如果是普通模組,絕對不允許是web工程,如果不需要依賴Spring絕對不允許成為Spring工程。因為嚴格控制Jar包依賴、工程性質是應對大型專案的有效手段。

當然嘍,Facets還有個作用是讓IDEA編譯器認識你的模組,比如如果你是個web模組,若沒有在Facets裡體現出來,那IDEA就不認識你,就無法給你提供web的一些便捷操作了。

Artifacts頁情況

IDEA如何打Jar包?如何打War包? 來,上菜~

在Maven大行其道的今天,雖然用IDEA打包很少使用了,但是有些時候它對你本地除錯還是蠻有用的,並且對理解maven的打包依舊有效,來,瞭解一下。

Artifacts這個概念不是特別好理解,artifact是maven裡的一個概念,被IDEA借鑑過來。表示某個模組要何種打包形式,如jar、war exploded、war、ear等等。Artifact是一個專案資源的組合體,整合編譯後的 java 檔案,資原始檔等。有不同的整合方式,比如jar、war、war exploded等等,對於一個module而言,有了Artifact就可以部署了,類似於maven的package打包。

說明:war 和 war exploded區別就是後者不壓縮,開發時選後者便於實時看到修改檔案後的效果

來個栗子,這裡演示下將hello模組打包成一個Jar:

配置好後,只需頂部選單欄Build -> Build Artifacts,就可以打出這個Jar包:

執行完此命令後,在Output Directory裡就能看到hello.jar這個打包好的檔案啦。然後java -jar .\hello.jar就能執行嘍(因為我們們打的是可執行Jar包)。關於使用IDEA打包還包括打可執行jar包、Fatjar、包外引用jar包等等,這裡就不展開了,後面會放在單獨文章裡把各種方式彙總在一起聊聊。

總的來說,無論配置Facets還是Artifacts,都是Intellij IDEA要求我們來做的(雖然有些可自動識別),目的是以便其能識別這些檔案並整合各外掛實現功能(如自動化配置、自動打包),一切為了編碼體驗和編碼效率。

模組如何依賴其它Module

一箇中大型專案一般有多個模組,它們各司其職。模組與模組之間一般都存在依賴關係,比如常見的xxx-core模組一般會被其它幾乎所有模組所依賴。模組依賴外部庫Library知道怎麼搞了,那麼如何增加本專案的模組依賴呢?

其實道理和步驟基本一樣,比如hello-core模組裡有個Person類:

hello-service模組也需要用到Person類及其功能,那麼就需要把hello-core模組依賴進來,操作步驟如下:

新增Dependency依賴時,請選擇Module Dependency...選項:

選擇本專案中需要依賴進來的模組:

選中hello-core模組把它依賴到hello-service裡來:

點選ok,搞定了。對應的,此依賴關係也會體現在hello-service.iml這個配置檔案上:

如此,我們就可以在hello-service模組里正常使用Person類啦:

public static void main(String[] args) {
    System.out.println(new Person());
}

完美。

總結

本文對IntelliJ IDEA的專案結構Project Structure的每個tab頁進行了全面分析,據我短淺的目光所及,可能是全網獨一份寫這個內容的。很多同學覺得IntelliJ IDEA不需要專門的學習分析,會用它匯入maven專案,跑跑main函式啟動下Spring Boot就成啦,我卻不以為然。

衡量一個新手和一個高手的差異不是順風順水時,而是遇到問題時誰能夠快速解決,誰又只能望洋興嘆,相信薪資的差異也體現在此。我見過的“高手”對自己最常用的工具用得都是很666的,這不正是技術範該有的樣子麼?說到底,我們不可能認為用一指禪敲程式碼的人會是大牛嘛~

好啦,關於IDEA的話題暫且先聊到這。其實我想到的主題還有好幾個,如:

  • IDEA如何主動去識別匯入不能被自動識別的Maven專案?原理是什麼呢?
  • IDEA如何打可執行Jar包?又如何打FatJar?如何打 包外Jar包(散包) 呢?
  • IDEA如何巧用其最新的Http Client指令碼能力,結合對Controller的嗅探快速完成本地測試?
  • ......

有你pick的嗎?歡迎留言告訴我,需求多就儘快上號,不然這個專題就暫時告一段落啦,把時間繼續花在其它專題上啦。

本文思考題

本文所屬專欄:IDEA,後臺回覆專欄名即可獲取全部內容。本文已被https://www.yourbatman.cn收錄。

看完了不一定懂,看懂了不一定會。來,文末3個思考題幫你覆盤:

  1. Module模組如何單獨設定JDK版本?
  2. IDEA如何打jar包?
  3. 開個腦洞:Maven用pom管理專案結構,IDEA是如何識別它的呢?

推薦閱讀

System.out.println("點個贊吧!");
print_r('關注【BAT的烏托邦】!');
var_dump('私聊A哥:fsx1056342982');
console.log("點個贊吧!");
NSLog(@"關注【BAT的烏托邦】!");
print("私聊A哥:fsx1056342982");
echo("點個贊吧!");
cout << "關注【BAT的烏托邦】!" << endl;
printf("私聊A哥:fsx1056342982");
Console.WriteLine("點個贊吧!");
fmt.Println("關注【BAT的烏托邦】!");
Response.Write("私聊A哥:fsx1056342982");
alert("點個贊吧!");

A哥(YourBatman):Spring Framework開源貢獻者,Java架構師,領域專家。文章不標題黨,不譁眾取寵,每篇文章都成系列去系統的攻破一個知識點,每個系列可能是全網最佳/唯一。注重基本功修養,底層基礎決定上層建築。現有IDEA系列、Spring N多系列、Bean Validation系列、日期時間系列......關注免費獲取

相關文章