訂製傢俱行業 ERP 供應商 RPC Software,憑藉 Eclipse RCP、OSGi、DotProject、SugarCRM 開源棧,擊敗傳統專有軟體競爭對手。本文深度剖析其 Core Business 產品線如何利用 OSGi 動態模組系統、Eclipse RCP 豐富客戶端框架、Tomcat 插件化改造,實現客戶端/伺服器端代碼複用、功能模組化交付、瀏覽器嵌入式報表整合的工程化最佳實踐。
客戶需求:銷售、報價、訂單、工時追蹤、倉儲、財務、報表全覆蓋,且需模組化升級、資料交換標準化 (OFDA-XML)、Web 協作門戶。RPC 方案三支柱:
兩資料庫整合實現 Core Business、Core Vision、Core CRM 三產品數據互通,單獨使用 DotProject/SugarCRM 無法做到。
OSGi 定義動態組件模型:Bundle 遠程安裝/啟動/更新/解除安裝無需重啟,服務註冊發現支援動態繫結。Eclipse RCP 架構於 OSGi 之上:
xsltTransforms 擴展,核心系統無感知即運行時自動採用新報表樣式 (XSLT)。挑戰:伺服器端需複用客戶端 Hibernate、Jasper Reports 等業務邏輯與第三方庫。傳統 WAR 打包導致構建腳本複雜、維護困難。
解決方案:讓 Tomcat「Plugin 化」:
servlet.jar 移入自建 Plugin,其他依賴 Servlet API 的 Plugin 即可複用。PluginClassLoaderWrapper 類別載入器,覆寫 getURLs() 收集 Plugin 依賴鏈的所有 Classpath (含 Bundle-Classpath、開發時路徑、RPC 自定義邏輯解析 Bundle 位置),解決 JSP 編譯器需要知道完整 Classpath 的難題。
// 關鍵片段:收集 Plugin 及其先決條件的所有 URLs
private Set getPluginClasspath(String pluginId) {
Set plugins = new HashSet();
addPluginWithPrereqs(pluginId, plugins); // 遞歸收集依賴
Set urls = new HashSet();
for (Iterator it = plugins.iterator(); it.hasNext();) {
String id = (String) it.next();
Bundle b = Platform.getBundle(id);
// 解析 Bundle-Classpath、處理 Bundle 位置 URL 轉換 (initial@reference:file:, update@ 等)
// RPC 自定義邏輯:從 Bundle Location 推導實際 Jar 路徑並加入 urls
}
return urls;
}
歷經 Apache FOP、Jasper Reports、Java Printing API 多工具並存,客戶需在客戶端無縫瀏覽伺服器端報表。SWT Browser 組件幾行代碼即刻實現:
final Browser browser = new Browser(shell, SWT.NONE);
browser.setUrl("https://server/report?type=pdf");
下拉組合框動態生成 URL 請求伺服器,實現報表類型客戶端選擇、伺服器端渲染、客戶端原生瀏覽一體化體驗。