DBeaver 自定义图表扩展实战:手把手把 ECharts 塞进数据库客户端

📅 2026/8/20 20:44:34
DBeaver 自定义图表扩展实战:手把手把 ECharts 塞进数据库客户端
DBeaver 自定义图表扩展实战手把手把 ECharts 塞进数据库客户端【免费下载链接】dbeaverFree universal database tool and SQL client项目地址: https://gitcode.com/GitHub_Trending/db/dbeaver本文要解决的核心关键词是「DBeaver 自定义图表扩展」。DBeaver 作为一款开源的通用数据库管理工具与 SQL 客户端内置图表功能只覆盖了折线图、柱状图等基础形态当业务方要求把查询结果渲染成桑基图、热力图时默认能力立刻见底。下面我们从一次真实的翻车现场出发讲清楚它的图表模块到底怎么运作再一步步实现第三方图表库的接入并盘点那些最容易踩的坑。一、先看翻车现场为什么原生图表撑不住故事是这样的某天数据分析组的同事丢来一张表要求把用户路径点对点画成桑基图。我打开 DBeaver 的视图图表功能左翻右翻——折线、柱状、饼图、散点齐了桑基图没有。再看一眼它的可视化插件org.jkiss.dbeaver.ui.charts底层绑定的是 JFreeChart而 JFreeChart 对桑基、热力、弦图这类高密度可视化几乎无解强行画出来不是丑就是卡。更扎心的是第二个问题主题色不跟随。DBeaver 的深色主题下默认色板是亮色系画出来的图在白底上尚可切到深色界面直接晃瞎眼。这说明原生图表模块的渲染管线是写死的不给你留换肤的余地。这里要敲个黑板凡是写死的渲染管线都值得你去翻它的插件注册机制。DBeaver 整个工程就是一堆 OSGi 插件拼起来的插件之间靠plugin.xml里的 extension 声明互相发现——这正是我们后续做扩展的钥匙。改造前先弄清钥匙孔长什么样这是本章最重要的结论。小结痛点 渲染能力单一 主题色无法联动突破口 OSGi 的钩子机制extension。二、原理先行图表模块的三层结构动手之前先把plugins/org.jkiss.dbeaver.ui.charts这个模块拆开看。它在项目里的真实路径是plugins/org.jkiss.dbeaver.ui.charts/ ├── plugin.xml # 主题色扩展点声明 ├── pom.xml # 版本 1.0.183-SNAPSHOTpackaging 为 eclipse-plugin ├── META-INF/MANIFEST.MF # OSGi 插件元信息 └── src/org/jkiss/dbeaver/ui/charts/ ├── BaseChartComposite.java # 图表组件基类继承 JFreeChart 的 ChartComposite ├── BaseChartConstants.java # 兜底色板10 种默认 Paint └── BaseChartDrawingSupplier.java # 颜色供给器从主题注册表读色这三层各自的分工是BaseChartConstants纯兜底。维护了一个Paint[]数组放着 10 种 RGB 颜色。它不参与渲染只在主题注册表读不到任何颜色时被调用——属于安全网角色。plugin.xml对外承诺。通过org.eclipse.ui.themes扩展点声明了 10 个colorDefinitionID 形如org.jkiss.dbeaver.ui.data.chart.color.1value 与BaseChartConstants一一对应。Eclipse 主题框架看到这份声明就会把这些颜色纳入配色体系用户可以在偏好设置里改。BaseChartDrawingSupplier动态读色。它继承 JFreeChart 的DefaultDrawingSupplier构造函数里调用UIUtils.getCurrentTheme().getColorRegistry()按color.1、color.2…… 依次去颜色注册表取值取不到就 fallback 到BaseChartConstants。看懂这三层你就理解了 DBeaver 图表配色的完整链路主题声明 → 注册表注入 → 供给器读取。而BaseChartComposite则是所有图表的宿主组件右键菜单、缩放、复制图片、存图这些交互都是它统一提供的。所以把新图表库塞进来的本质是什么不是重写整个模块而是在同一个宿主里换一个渲染内核保留BaseChartComposite的交互外壳把内核从 JFreeChart 换成浏览器渲染的 ECharts。小结配色链是声明-注入-读取组件外壳与渲染内核是可分离的——这就是我们下刀的位置。三、动手搭骨架扩展插件怎么声明出来既然要走 OSGi 的钩子机制第一步就是新建一个独立的插件工程模仿项目里其他插件的组织方式。建议目录如下plugins/org.jkiss.dbeaver.ui.charts.ext/ ├── META-INF/MANIFEST.MF # 声明插件名、依赖、导出包 ├── plugin.xml # 注册自定义扩展点 ├── pom.xml # 继承父 POMpackaging eclipse-plugin └── src/org/jkiss/dbeaver/ui/charts/ext/ ├── EChartsProvider.java # 渲染实现 └── ChartExtension.java # 插件激活器可选pom.xml里两个关键点缺一个都会翻车parent groupIdorg.jkiss.dbeaver/groupId artifactIdplugins/artifactId version1.0.0-SNAPSHOT/version relativePath..//relativePath /parent artifactIdorg.jkiss.dbeaver.ui.charts.ext/artifactId packagingeclipse-plugin/packaging为什么这样写parent指向plugins聚合模块这样能继承整个工程的依赖管理和版本约定packaging必须是eclipse-pluginTycho 构建器靠它识别这是一个 OSGi 插件而不是普通 jar。如果漏了relativePath在本地构建时 Maven 可能找不到父 POM 而直接报Non-resolvable parent POM。然后是plugin.xml。这里要特别注意org.jkiss.dbeaver.dataVisualization.chartProvider这个扩展点并不存在于当前版本网上很多教程直接照抄老版本结果 IDE 里飘红一片。正确做法是自己定义一个扩展点 schema再声明实现extension-point idchartProvider nameChart Provider schemaschema/chartProvider.exsd/ extension pointorg.jkiss.dbeaver.ui.charts.ext.chartProvider provider classorg.jkiss.dbeaver.ui.charts.ext.EChartsProvider idecharts.provider supportedTypesline,bar,pie,heatmap,sankey/ /extension为什么这样写extension-point 是钩子的定义extension 是钩子上挂的东西。DBeaver 官方插件比如 dashboard就是这么做的——你可以直接看plugins/org.jkiss.dbeaver.model.dashboard/plugin.xml里的org.jkiss.dbeaver.dashboard扩展点是怎么声明的照着它的模式来比自己发明一套稳妥得多。小结骨架 标准 OSGi 插件 自声明扩展点先模仿项目里已有的 dashboard 插件能少走一半弯路。四、核心实现用浏览器组件接住 ECharts内核替换的思路定了SWT 的Browser组件内嵌 Chromium我们在页面里加载 ECharts 的 JS把查询结果 JSON 化后通过execute注入。渲染实现类长这样package org.jkiss.dbeaver.ui.charts.ext; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.widgets.Composite; import org.jkiss.dbeaver.ui.charts.BaseChartComposite; public class EChartsProvider { /** * 宿主组件直接复用 BaseChartComposite 的交互外壳 * 这样右键菜单、复制、导出这些能力是白捡的 */ public BaseChartComposite createChart(Composite parent) { Browser browser new Browser(parent, SWT.NONE); browser.setUrl(file:///plugins/echarts/echarts.min.html); return new BaseChartComposite(parent, SWT.NONE, browser.getSize()) { Override public void paintControl(org.eclipse.swt.events.PaintEvent e) { // 把浏览器画布叠到图表组件上避免双画布闪烁 } }; } /** * 数据 → ECharts option只做结构映射不做业务判断 * 这里用 StringBuilder 手拼 JSON避免引入额外依赖 */ public String toEChartsOption(String[] categories, String[][] seriesData) { StringBuilder sb new StringBuilder(); sb.append({\xAxis\:{\data\:[); // 逐项拼接注意转义引号JS 端才能正确 parse for (String c : categories) { sb.append().append(c).append(\,); } sb.append(]},\series\:[{\type\:\bar\,\data\:[); // ... 同理拼接数据列 sb.append(]}); return sb.toString(); } public void render(Browser browser, String option) { // execute 的字符串里不能再拼用户输入防止脚本注入 browser.execute( const chart echarts.init(document.getElementById(chartBox)); chart.setOption(%s); window.addEventListener(resize, () chart.resize()); .formatted(option)); } }这里有三处容易翻车逐个说明为什么用Browser而不是画 CanvasECharts 本身就是 DOM 渲染你不可能在 SWT 里复刻它的 SVG/Canvas 输出。用浏览器组件是最短路径代价是多一个内嵌内核内存占用会上去——所以懒加载很重要只在用户真正打开图表时才创建Browser。为什么数据要手拼 JSON项目里不希望你为一个小功能引入 Gson 全家桶手拼虽然丑但零依赖、可控。前提是先转义再拼接categories里一旦出现双引号或换行整个 option 就废了。为什么execute里要警惕拼接formatted注入的 option 若含/script或引号轻则渲染失败重则脚本注入。生产环境请用JSONObject.quote()之类工具做转义别学我偷懒。小结核心 浏览器组件接渲染 JSON 桥接数据三个坑分别是性能、转义、注入。五、踩坑手册主题色、版本、类加载三连这一章把最常见的报错和翻车点集中摆出来按症状→原因→解法写方便你直接检索。坑一深色主题下图表刺眼颜色纹丝不动症状切到深色主题自定义图表还是亮色系原生图表却能跟着变。 原因我们的渲染完全走浏览器BaseChartDrawingSupplier那套主题注册表读色的链路只服务于 JFreeChart 内核。 解法渲染前显式读取主题色把 RGB 转成十六进制塞进 optionColorRegistry registry UIUtils.getCurrentTheme().getColorRegistry(); Color c registry.get(org.jkiss.dbeaver.ui.data.chart.color.1); String hex String.format(#%02x%02x%02x, c.getRed(), c.getGreen(), c.getBlue());为什么这样写颜色 ID 就是plugin.xml里声明的那些colorDefinition官方配色体系对我们是开放的读出来复用即可保证主题切、图表切。坑二构建报Cannot find dependency/ 版本冲突症状mvn package时 Tycho 找不到org.jkiss.dbeaver.ui.charts或者运行时ClassNotFound。 原因版本号对不上。当前仓库里org.jkiss.dbeaver.ui.charts的版本是1.0.183-SNAPSHOT很多旧博客写的是1.0.128照抄必炸。 解法先在pom.xml里把父版本改为1.0.0-SNAPSHOT沿用聚合模块约定再在MANIFEST.MF里用版本范围声明依赖而不是写死精确版本Require-Bundle: org.jkiss.dbeaver.ui.charts;bundle-version[1.0.0,2.0.0)坑三Browser创建后界面卡死 / 白屏症状图表区域白屏主线程卡顿控制台刷 SWT 报错。 原因在 UI 线程同步加载本地大页面或者Browser在非 display 线程创建。SWT 组件只能在 UI 线程创建这是最容易被忽略的纪律。 解法图表组件一律在 UI 线程回调里创建页面资源echarts.min.js、HTML预先拷到插件 bundle 目录用bundle.getEntry()取 URL不要依赖工作目录的相对路径。小结三个坑对应三条纪律——颜色要主动读主题、版本要对齐当前仓库、SWT 组件别跨线程。六、验证、发布与长期主义验证清单按这个顺序过一遍缺一不可mvn clean verify -Pdebug能起调试实例插件无 error 日志打开任意查询结果 → 图表 → 选择echarts.provider桑基图能渲染切换浅色/深色主题图表配色跟随变化放大窗口图表随resize自适应不闪烁右键菜单复制图片、另存为 PNG 均可用这继承自BaseChartComposite。发布就两步mvn package -DskipTests打出插件 jar把target/*.jar丢进 DBeaver 安装目录的plugins/文件夹重启即可。注意别用mvn install:install-file硬塞本地仓库Tycho 构建不认这种手工安装的包老老实实走mvn package才是正路。最后聊两句长期主义这次扩展如果只想顶一时的需求到上面就够了但如果你要长期维护建议后续把数据采样、option 缓存、懒加载做成可配置项——数据量上万行时每次全量重建 option 会让浏览器卡到怀疑人生参照原生图表的降采样思路提前设计比事后补课便宜得多。行动号召现在就打开 DBeaver 源码仓库https://gitcode.com/GitHub_Trending/db/dbeaver把plugins/org.jkiss.dbeaver.ui.charts三个类通读一遍再对照plugins/org.jkiss.dbeaver.model.dashboard/plugin.xml抄一份自己的扩展点声明。按上面五步清单过一遍验证你就能在 DBeaver 里渲染任意你想得到的图表类型了。扩展能力从来不是框架白送的而是你摸清钩子机制之后自己挣来的。【免费下载链接】dbeaverFree universal database tool and SQL client项目地址: https://gitcode.com/GitHub_Trending/db/dbeaver创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考