目前網上已經有了很多關於IDEA(IntelliJ平台)的插件開發教程了,本人覺得簡書上這位作者秋水畏寒 的關於插件開發的文章很不錯,在我進行插件開發的過程中指導了我很多。但是綜合下來看,在IDEA上加載網頁的插件的教程還不是特別多,官方文檔也不是那么的完整。本系列將會從這個角度出發,探討如何編寫加載Web頁面的插件。
前言
為什么會有想到開發處理Web網頁的插件呢?實際上因為在IDEA中,我們可以打開markdown文件,並且IDEA具有markdown實時渲染的能力:
因為之前,本人使用過JCEF進行開發。看到這個渲染,心里大概猜測,應該用了瀏覽器內核。打開任務管理器:
果然,熟悉的JCEF。然后進入JetBrains的官網,在插件開發的文檔中找到了:JCEF - Java Chromium Embedded Framework | IntelliJ Platform Plugin SDK (jetbrains.com)。
那么,接下來我們從零開始,編寫一款屬於自己的插件,這款插件能夠加載Web頁面。
環境准備
- JDK 11
- Gradle
- 良好的網絡環境
我們先創建一個IntelliJ Platform Plugin,名為:intellij-jcef-plugin
然后進行這個Gradle項目的配置工作,完成整個項目搭建。本項目會在最后提交到github供讀者下載。
代碼編寫
首先說明我們的目的,就是希望能夠類似於gradle、maven插件一樣,能夠在IDEA的側邊有一個顯示我們Web頁面的地方:
通過閱讀官方的文檔我們可以知道,我們需要編寫的是ToolWindow(Tool Windows | IntelliJ Platform Plugin SDK (jetbrains.com))這樣一個頁面窗體。
基礎ToolWindow開發
在開發之前,我們需要明確一點,盡管這一節的標題寫着"空白ToolWindow開發",似乎在暗示我們,接下來我們會開發一個所謂的ToolWindow的實現類。實際上,ToolWindow是插件框架本身提供的,我們只需要做的是創建UI組件(例如JPanel),然后調用ToolWindow實例通過相關的API幫我們把UI組件設置到ToolWindow內部,具體的步驟如下:
實現ToolWindowFactory
創建一個ToolWindowFactory的實現類,這里我們取名MyToolWindowFactory,然后重寫createToolWindowContent
方法。
public class MyToolWindowFactory implements ToolWindowFactory {
@Override
public void createToolWindowContent(
@NotNull Project project,
@NotNull ToolWindow toolWindow) {
// 此處方法將會在點擊ToolWindow的時候觸發
// 獲取ContentManager
ContentManager contentManager = toolWindow.getContentManager();
Content labelContent =
contentManager.getFactory() // 內容管理器獲取工廠類
.createContent( // 創建Content(組件類實例、顯示名稱、是否可以鎖定)
new JLabel("hello, world"),
"MyTab",
false
);
// 利用ContentManager添加Content
contentManager.addContent(labelContent);
}
}
在重寫的createToolWindowContent
方法中,插件框架會為我們傳入兩個對象:Project以及ToolWindow對象。其中,Project對象是當前項目的內容抽象,而ToolWindow這個對象就是插件框架本身內部構造的,抽象了我們需求所說的,點擊側邊欄時候彈出的頁面。
在該方法實現中,主要有以下步驟:
- 使用ContentFactory(ContentManager.getFactory()獲取)的
createContent
API創建Content對象。這個創建時候,需要swing組件對象(JPanel、JLabel等等)。 - 使用ContentManager的
addContent
API添加步驟1的Content對象。
注冊插件
接下來,我們將我們實現的MyToolWindowFactory通過plugin.xml
進行注冊,alt+enter
,IDEA幫助我們快速完成填寫xml配置到plugin.xml
中:
進行上述操作后,IDEA自動為我們在plugin.xml文件的extensions節點
中,添加了toolWindow節點
的內容,但是我們還需要填寫必備的屬性id
:
<!-- plugin.xml文件 -->
<extensions defaultextensionns="com.intellij">
<!-- Add your extensions here -->
<!-- id是必須的屬性,我們進行添加 -->
<!-- anchor錨點非必須,但是為了像Gradle插件一樣默認顯示在右邊,我們設置為right -->
<toolwindow id="myToolWindowFactory" anchor="right" factoryclass="com.compilemind.demo.ui.MyToolWindowFactory">
</toolwindow></extensions>
解決調試環境問題
目前為止,我們實現了ToolWindowFactory以及將我們的實現類注冊到plugin.xml中。現在,我們先什么內容都不編寫,開始調試我們的插件:
不過開始調試后,會有很多的情況發生,這里我做了一些遇到的問題的總結。
Gradle亂碼
此時進行Debug調試,在我的機器上會出現亂碼:
解決方案為,在build.gradle中添加如下的語句:
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
Gradle報錯不知道這樣的主機(Unknown host)
如果出現了類似於Unknown host 'xxxxx.cloudfront.net'. You may need to adjust the proxy settings in Gradle.
這樣的報錯,一般是當前網絡的連通問題,導致無法下載cloudfront.net一些jar文件。此時掛代理是最好的辦法。
rumIde:Download JCEF
如果使用調試模式,intellij插件開發的Gradle插件會下載jcef的運行時,這個過程會比較漫長,目前解決辦法是使用好的網絡等待下載:
在本人機器上,第一次調試的時候主要就是遇到上面的三種情況。
驗證基礎ToolWindow
解決完上述的幾個問題之后,界面彈出了我們的調試下的社區版的IDEA(ideaIC),並且,查看Plugins頁簽,會發現我們編寫的插件已經被這個ideaIC安裝了:
我們使用這個IDEA創建一個簡單的空項目,然后可以看到右側有我們提供的ToolWindow:
可以看到,此時的ToolWindow中的內容顯示為我們上面設置的new JLabel("hello, world")
,該ToolWindow上方有我們設置的"My Tab"標題。截至目前的代碼,包含在這個github上這個提交:
simple ToolWindow Content · w4ngzhen/intellij-jcef-plugin@bf2ca8e (github.com)
Web頁面ToolWindow開發
通過上面一些系列的環境搭建,以及ToolWindow開發練習,我們已經了解了如何開發一款用於IDEA側邊欄展示內容的插件。當然,我們一開始的需求是要在ToolWindow中展示網頁,並且也知道了,JetBrains已經將JCEF引入到了IntelliJ插件平台。接下來,我們使用JCef以及JBCef相關API創建一個用於展示Web的UI組件,再通過上述的方式,添加到ToolWindow。
創建MyWebToolWindowContent
package com.compilemind.demo.ui;
import com.intellij.ui.jcef.JBCefApp;
import com.intellij.ui.jcef.JBCefBrowser;
import javax.swing.*;
import java.awt.*;
public class MyWebToolWindowContent {
private final JPanel content;
/**
* 構造函數
*/
public MyWebToolWindowContent() {
this.content = new JPanel(new BorderLayout());
// 判斷所處的IDEA環境是否支持JCEF
if (!JBCefApp.isSupported()) {
this.content.add(new JLabel("當前環境不支持JCEF", SwingConstants.CENTER));
return;
}
// 創建 JBCefBrowser
JBCefBrowser jbCefBrowser = new JBCefBrowser();
// 將 JBCefBrowser 的UI控件設置到Panel中
this.content.add(jbCefBrowser.getComponent(), BorderLayout.CENTER);
// 加載URL
jbCefBrowser.loadURL("https://cnblogs.com/w4ngzhen");
}
/**
* 返回創建的JPanel
* @return JPanel
*/
public JPanel getContent() {
return content;
}
}
修改MyToolWindowFactory
這里,我們將創建MyWebToolWindowContent
實例,然后返回其Panel,按同樣的方式設置到ToolWindow中。
驗證Web渲染ToolWindow
上述代碼完成開發后,我們再次運行Debug模式,可以看到此時的界面顯示了相關的網頁:
附錄
本次代碼本人放在了Github上,地址為:w4ngzhen/intellij-jcef-plugin (github.com)。
上面基礎ToolWindow開發以及web頁面ToolWindow開發兩節的內容,按如下提交對應:
基礎ToolWindow開發 :simple ToolWindow Content · w4ngzhen/intellij-jcef-plugin@bf2ca8e (github.com)
web頁面ToolWindow開發:web ToolWindow Content · w4ngzhen/intellij-jcef-plugin@45604d3 (github.com)