作者:小傅哥
部落格:https://bugstack.cn
沉澱、分享、成長,讓自己和他人都能有所收穫!?
一、前言
不踩些坑,根本不是成熟的碼農!
你覺得肯德基全家桶是什麼?一家人一起吃的桶嗎,就那麼一點點?不是,肯德基全家桶說的是,雞的全家桶!
聽到這個故事就像有時候我因為需要解決某些問題去搜尋
、折騰
、驗證
、排除
的技術方案,因為方向不對,所以努力也就白費。只能一次次在眾多的資料、文件、原始碼中一點點找到並組合出適合自己的問題場景的技術處理手段。
但這個過程有時候又是必須經歷的,很少有時候能一次就找到正確的答案或者人,哪怕開始就找到了,也會再去排查下其他的資料,看看還有沒有更好的。是不,這就是你吧?
二、丟擲問題
我又要衝IDEA外掛開發了!
在研究位元組碼插樁的相關技術後,?考慮著除了通常的用在程式碼上線後的非入侵式監控外,是不是也可以用於研發在開發階段對系統介面的提取呢?
帶著這個從腦袋中冒出的想法,想到如果要處理這個事情,最核心的問題就是開發一款IDEA外掛+位元組碼插樁能力,在程式碼執行時對執行方法增強,提取相關的必要資訊。別說案例還真做出來了,如下:
- 案例地址:基於IDEA外掛開發和位元組碼插樁技術,實現研發交付質量自動分析
- 後續問題:其實實現到這裡還只能算是一個案例,對於 IDEA 外掛開發能力並沒有完全弄透,比如這個 IDEA 外掛需要做一些基礎配置,那麼在哪裡開啟呢?還有實時監控併產生的介面資訊能在 IDEA 介面右側展示出來或者支援匯出嗎?如果我再有一些集合 IDEA 外掛開發的能力做的其他的功能引入咋辦呢?這裡用到了哪些技術呢?等等,這些問題都需要去一一解決掉,才能完完整整的開發一個可用的 IDEA 外掛,為此,需要做更深入的資料整理和實踐驗證。
三、開發外掛涉及的問題
問題彙總:開發一個 IDEA 外掛基本要涉及到的問題過程如下:
- 開發方式:在官網的描述中,建立IDEA外掛工程的方式有兩種分別是,IntelliJ Platform Plugin 模版建立和 Gradle 構建方式。
- 框架入口:一個 IDEA 外掛開發完,要考慮把它嵌入到哪,比如是從 IDEA 窗體的 Edit、Tools 等進入配置還是把窗體嵌入到左、右工具條還是IDEA窗體下的對話方塊。
- UI:思考的是窗體需要用到什麼語言開發,沒錯,用的就是 Swing、Awt 的技術能力。
- API:在 IDEA 外掛開發中,一般都是圍繞工程進行的,那麼基本要從通過 IDEA 外掛 JDK 開發能力中獲取到工程資訊、類資訊、檔案資訊等。
- 外部功能:這一個是用於把外掛能力與外部系統結合,比如你是需要把拿到的介面上傳到伺服器,還是從遠端下載檔案等等。
四、開發外掛的兩種配置
- 官方文件:https://plugins.jetbrains.com/docs/intellij/disposers.html
- 官方案例:https://github.com/JetBrains/intellij-sdk-docs
1. 基礎配置
-
IntelliJ IDEA 2019.3.1 x64
-
JDK 需要配置 IntelliJ Platform Plugin JDK,在 Project Setting 中設定,這樣才可以正常開發 IDEA 外掛
-
id 'org.jetbrains.intellij' version '0.6.3'
-
gradle-5.2.1
與 2019 IDEA 版本下的外掛開發匹配
-
Settings -> Build, Execution,Deloyment -> Build Tools,配置 Gradle。Gradle user home =
D:/Program Files (x86)/gradle/gradle-5.2.1/.gradle
User Gradle from =gradle-wrapper.properties
或者Specified location
具體如下圖:
如果你是使用 IDEA New Project 預設的 IntelliJ Platform Plugin 方式,其實只關注1、2兩步驟就可以了,但如果你需要 Gradle,那麼需要注意3、4、5步驟的設定。當然通常也更推薦使用 Gradle 來搭建工程,這樣你在需要一些額外的 Jar 包時候,只需要在 Gradle build.gradle
配置即可,而不是把需要的 Jar 包複製到工程的 lib 下。
2. 遇到問題
在使用 Gradle 構建專案後,你會遇到幾個問題;
- 提前下載好 Gradle 5.2.1 版本並配置上,否則構建工程自動下載會比較慢 https://gradle.org/next-steps/?version=5.2.1&format=all
- 構建工程時候拉取相關內容,會比較慢,如果你有代理會好一些。
- 【麻煩的問題】基於 Gradle 的 IDEA 外掛開發會在構建過程中,會下載一個匹配版本的 IDEA 軟體用於啟動測試開發外掛,幾百兆那種zip包
ideaIC-2019.3.1.zip
。這個時候基本你會遇到一個崩潰的報錯Could not resolve all files for configuration ':detachedConfiguration1'.
咋辦呢,如果你不嫌棄麻煩可以手動下載並SHA1加密後把下載的檔案放到快取資料夾中.gradle\caches\modules-2\files-2.1
具體操作如下:- 開啟系統盤下當前使用者的
.gradle
目錄,進入.gradle\caches\modules-2\files-2.1
目錄,即為快取檔案的目錄。這個目錄是你的報錯構建過程中的報錯地址,Could not get resource D:\Program Files (x86)\gradle\gradle-5.2.1\.gradle\caches\modules-2\files-2.1\com.jetbrains.intellij.idea\ideaIC\2019.3.1
- 加密資料夾
2dae8e50d4b0508cad2e680b53414f657954f390
目錄名稱(你的可能不是這樣的),我去,這個應該是加密過的,但是是什麼加密呢?,經過了解知道了這個是SHA1
加密,且是對檔案進行SHA1
的加密生成的唯一字串,但是windows上沒有這個命令,線上SHA1
也太麻煩了,還要上傳檔案,於是想到了Java的API,還有就是通過git hash
命令列來實現。 把我們的檔案ideaIC-2019.3.1.zip
先臨時拷貝到這個目錄。執行sha1sum.exe ideaIC-2019.3.1.zip
命令,生成唯一的唯一字串(用來校驗檔案的完整性),這樣就拿到這個2dae8e50d4b0508cad2e680b53414f657954f390
目錄名 - 接下來在
2019.3.1
目錄下,新建目錄2dae8e50d4b0508cad2e680b53414f657954f390
,將ideaIC-2019.3.1.zip
移動進去即可。
- 開啟系統盤下當前使用者的
- 【堆疊溢位】在 Gradle 構建的過程中,消耗記憶體較大,可能會報錯
Java heap space
所以也可以 在IDEA專案根目錄下,新建檔案gradle.properties
,新增如下內容,變更gradle Jvm引數org.gradle.jvmargs=-Xmx2024m -XX:MaxPermSize=512m
別說還挺好用,竟然構建成功了。
五、寫個測試案例
1. 工程結構
PluginGuide
├── .gradle
└── src
├── main
│ └── java
│ ├── HiClazz.java
│ ├── MyDumbAwareAction.java
│ ├── MySearchableConfigurable.java
│ ├── MyToolWindowFactory.java
│ └── TestUI.java
└── resources
├── icons
└── META-INF
└── plugin.xml
- HiClazz 是繼承 AnAction 的實現類,用於附著到 IDEA 的窗體上,點選後開啟對應頁面
- MyDumbAwareAction、MyToolWindowFactory,配合使用,用於在 IDEA 最下面的窗體設定,與你看見的控制檯輸出資訊位置一樣。
- MySearchableConfigurable,可以用於 Settings 中配置窗體。
- TestUI 是基於 Swing 開發的窗體,驗證在 AnAction 實現類中開啟。
- plugin.xml 是整個 IDEA 咖啡的配置檔案,你所有的窗體都會在這個配置檔案裡有所體現。
2. AnAction
public class HiClazz extends AnAction {
@Override
public void actionPerformed(AnActionEvent e) {
Project project = e.getData(PlatformDataKeys.PROJECT);
PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE);
String classPath = psiFile.getVirtualFile().getPath();
String title = "Hello World!";
Messages.showMessageDialog(project, classPath, title, Messages.getInformationIcon());
}
}
- 測試在 IDEA 中讀取滑鼠停留在類檔案中的資訊。我們可以把這個 AnAction 配置到各個 IDEA 選單中。
3. MyToolWindowFactory
public class MyToolWindowFactory implements ToolWindowFactory {
@Override
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
toolWindow.setToHideOnEmptyContent(true);
class MyPanel extends SimpleToolWindowPanel {
public MyPanel(boolean vertical) {
super(vertical);
DefaultActionGroup group = new DefaultActionGroup();
group.add(new MyDumbAwareAction("Login1"));
group.add(new MyDumbAwareAction("Login2"));
group.add(new MyDumbAwareAction("Login3"));
ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar("ToolBar", group, false);
setToolbar(toolbar.getComponent());
}
}
// 新增一個頁
toolWindow.getContentManager().addContent(ContentFactory.SERVICE.getInstance().createContent(new MyPanel(false), "First", false), 0);
}
}
- 在 IDEA 的最下面窗體中,如果想展示自己的窗體,則需要開發對應的 ToolWindowFactory 實現類,這樣才可以展示你的內容。
- 這裡的思想基本是 Swing 技術的開發方式,如果你不熟悉 Swing 最這塊內容會比較陌生。
4. plugin.xml
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<toolWindow canCloseContents="true" anchor="bottom"
id="SmartIM"
factoryClass="MyToolWindowFactory">
</toolWindow>
<!-- 在Setting中新增自定義配置模版 -->
<projectConfigurable groupId="Other Settings" displayName="My Config" id="thief.id"
instance="MySearchableConfigurable"/>
</extensions>
<actions>
<!-- Add your actions here -->
<action id="HiId_FileMenu" class="HiClazz" text="HiName">
<add-to-group group-id="FileMenu" anchor="first"/>
<add-to-group group-id="MainMenu" anchor="first"/>
<add-to-group group-id="EditMenu" anchor="first"/>
<add-to-group group-id="ViewMenu" anchor="first"/>
<add-to-group group-id="CodeMenu" anchor="first"/>
<add-to-group group-id="AnalyzeMenu" anchor="first"/>
<add-to-group group-id="RefactoringMenu" anchor="first"/>
<add-to-group group-id="BuildMenu" anchor="first"/>
<add-to-group group-id="RunMenu" anchor="first"/>
<add-to-group group-id="ToolsMenu" anchor="first"/>
<add-to-group group-id="WindowMenu" anchor="first"/>
<add-to-group group-id="HelpMenu" anchor="first"/>
</action>
<action id="HiId_EditorPopupMenu" class="HiClazz" text="HiName">
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
</action>
<action id="HiId_MainToolBar" class="HiClazz" text="HiName">
<add-to-group group-id="MainToolBar" anchor="first"/>
</action>
</actions>
- 在 plugin.xml 的配置中,主要是把各個功能實現窗體配置到對應的選單下,比如 Tools 下、toolWindow 裡等。
5. 測試結果
啟動執行
- IDEA 外掛開發執行會基於 Plugin 或者 Gradle 下配置的
::runIde
執行介面
- 在 IDEA 的各個選單中都可以看到新增加的 HiName 外掛,在你實際開發的時候選擇需要的內容進行配置即可。
執行效果
- 當滑鼠點到類的上,在點 HiName 就可以看到對應的工程類資訊了。
六、外掛開發能做啥都
在 GitHub 上搜尋 IDEA 外掛開發,一共有44頁內容,https://github.com/search?p=41&q=idea%E6%8F%92%E4%BB%B6&type=Repositories 涉及到自動化測試、工程腳手架、API生成、生成資料庫的DAO類、一些常用工具,當然還有一些比較有意思的,比如:摸魚看書、聽郭德綱相聲、微信聊天、區域網聊天、英語翻譯等等。這裡我給大家列舉幾個,開闊開闊思路。
1. 快速生成 CRUD 工程程式碼
- 地址:https://github.com/mars05/crud-intellij-plugin
- 描述:一個增刪改查的idea外掛,可以根據資料庫表結構,幫助您快速生成model、dao、service、controller等相關程式碼。同時支援MyBatis、JPA、MybatisPlus。
2. 在 IDEA 中摸魚聊天
- 地址:https://github.com/Jamling/SmartIM4IntelliJ
- 描述:ntelliJ IDEA上的SmartIM(原SmartQQ)外掛,可以在IDEA中使用QQ或微信聊天。安裝成功後,會在底部欄出現一個SmartIM的tab(如果沒有底部欄,則在選單View中把ToolButtons勾選上)
3. 視覺化流程編排
- 地址:https://github.com/alibaba/compileflow
- 描述:
compileflow Process
引擎是淘寶工作流TBBPM
引擎之一,是專注於純記憶體執行,無狀態的流程引擎,通過將流程檔案轉換生成java
程式碼編譯執行,簡潔高效。當前是阿里業務中臺交易等多個核心繫統的流程引擎。在阿里巴巴中臺解決方案中廣泛使用,支撐了導購、交易、履約、資金等多個業務場景。
七、總結
- IDEA 開發技術涉及到了對 IDEA 外掛開發 API 的熟悉以及UI介面的開發,所以如果想開發一款 IDEA 外掛,基本離不開對 Swing 的編寫,不過也不需要太複雜的頁面,所有這部分技能還好。
- IDEA 官網文件僅提供了兩種構建 IDEA 外掛工程的方法,但更推薦 Gradle 方式,這樣可以滿足你對後續其他功能元件的便捷引入,以及做其他內容的擴充套件。
- IDEA 外掛開發可以開發出很多用於提效研發程式設計的技術外掛,例如一些監控、腳手架、介面API以及除錯、流程化低程式碼編排等等,所以這部分內容的價值還是蠻大的。