目前网上已经有了很多关于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这个对象就是插件框架本身内部构造的,抽象了我们需求所说的,点击侧边栏时候弹出的页面。

在该方法实现中,主要有以下步骤:

  1. 使用ContentFactory(ContentManager.getFactory()获取)的createContentAPI创建Content对象。这个创建时候,需要swing组件对象(JPanel、JLabel等等)。
  2. 使用ContentManager的addContentAPI添加步骤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)

IDEA Web渲染插件开发(一)— 使用JCEF的更多相关文章

  1. IDEA Web渲染插件开发(二)— 自定义JsDialog

    <IDEA Web渲染插件开发(一)>中,我们了解到了如何编写一款用于显示网页的插件,所需要的核心知识点就是IDEA插件开发和JCEF,在本文中,我们将继续插件的开发,为该插件的JS Di ...

  2. (转)openfire插件开发(二) 基于web的插件开发

    转:http://blog.csdn.net/lovexieyuan520/article/details/38935137 在前面的博客中,我介绍了openfire插件开发,在那篇博客中我详细的说明 ...

  3. java web渲染器

    渲染就是server端将夹杂有脚本语言变量对象的模版文件解释为纯html页面的过程!

  4. [ Python ] Flask 基于 Web开发 大型程序的结构实例解析

    作为一个编程入门新手,Flask是我接触到的第一个Web框架.想要深入学习,就从<FlaskWeb开发:基于Python的Web应用开发实战>这本书入手,本书由于是翻译过来的中文版,理解起 ...

  5. 使用electron进行原生应用的打包(2)---主进程与渲染进程之间的通信

    上一篇讲了使用electron进行打包的配置相关文件,这篇主要讲electron中很重要的通信方式. 首先解释一个概念: electron打包的应用包含两个部分 electron的环境(node),也 ...

  6. Beetl学习总结(4)——Web集成

    4.1. Web提供的全局变量 Web集成模块向模板提供web标准的变量,做如下说明 request 中的所有attribute.在模板中可以直接通过attribute name 来引用,如在cont ...

  7. 【Web技术】 275- 理解 WebView

    前言 了解webview的神秘之处.今日早读文章由@子非翻译分享. 正文从这开始-- 我们通常使用 Chrome, Firefox, Safari, Internet Explorer 和 Edge ...

  8. 移动APP开发框架盘点2:Web移动前端框架大全

    前言 自上次发布了<移动APP开发框架盘点>后,时间已经过去了三年, 为什么突然又写一篇续集呢?是因为有一个非常有意思的发现. 开源项目其实有一个成熟周期,这个周期大概是三年左右,自Rea ...

  9. WebKit技术内幕

    WebKit技术内幕(浏览器内核|渲染引擎| HTML5| Chromium项目Committer重磅作品) 朱永盛 著   ISBN 978-7-121-22964-0 2014年6月出版 定价:7 ...

随机推荐

  1. mysql主要的两个索引Innodb和MyIASM。

    参考:https://www.cnblogs.com/xiaohaillong/p/6079551.html 1. a.Innodb引擎,Innodb引擎提供了对数据库ACID事务的支持.并且还提供了 ...

  2. springboot开启矩阵传参MatrixVariable

    /** *   根据 URI 规范 RFC 3986 中 URL 的定义,路径片段中可以可以包含键值对. * 规范中没对对应的术语.一般 "URL 路径参数" 可以被应用,尽管更加 ...

  3. IP掩码的作用

    IP地址&IP掩码==网段,即,与上掩码后相同的IP属于同一网段.

  4. MutationObserver API

    1.概述 MutationObserver接口提供了监视对DOM树所做更改的能力.它被设计为旧的Mutation Events功能的替代品,该功能是DOM3 Events规范的一部分. 但是,它与Mu ...

  5. 日常shell练习

    2021-07-19 1.echo的使用 1.1 echo -n 表示不换行输出 # echo输出会自动换行,换行输出两个1 echo 1 echo 1 # 不换行输出,不换行输出两个1 echo - ...

  6. MyBatis学习总结(一)——MyBatis入门学习

    一.MyBatis 简介 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可 ...

  7. 剑指offer计划9(动态规划中等版)---java

    1.1.题目1 剑指 Offer 42. 连续子数组的最大和 1.2.解法 得到转移方程后,单次遍历. 当前面的连续子数组的和比较是否大于0,是则加起来, 若小于零,则当前的值就可当子数组的开头. 判 ...

  8. UNION / UNION ALL 区别

    Union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序: Union All:对两个结果集进行并集操作,包括重复行,不进行排序: 使用union all: select top 5 ...

  9. 20210808 Hunter,Defence,Connect

    考场 乍一看都不可做 T1 算了半天样例,一直算出来 \(\frac{81}{400}\),直接丢了 T1 推了推发现是求最长连续 \(0\) 的数量,那就是线段树合并加上<玫瑰花精> T ...

  10. Python习题集(六)

    每天一习题,提升Python不是问题!!有更简洁的写法请评论告知我! https://www.cnblogs.com/poloyy/category/1676599.html 题目 ''' 问题1.对 ...