某資訊系統採用 Java Applet 呈現豐富客戶端介面,但 Java 列印 API 功能薄弱,難以輸出複雜單據報表。方案:在網頁內嵌隱藏的 ActiveX 控件——華表 Cell 插件(類 Excel 試算表元件),Applet 透過 JavaScript 橋接器將資料與格式推送給 Cell,由 Cell 負責分頁預覽與列印。
| 層級 | 技術 | 角色 |
|---|---|---|
| 表示層 | Java Applet (Swing) | 業務邏輯、資料收集、使用者互動 |
| 橋接層 | JavaScript + netscape.javascript.JSObject | Applet ↔ DOM ↔ ActiveX 通訊 |
| 列印層 | Cell ActiveX (CellPlugin.ocx) | 儲存格級排版、分頁、列印預覽、匯出 Excel/PDF |
jre/lib/jaws.jar 加入 classpath(提供 netscape.javascript.JSObject)。<OBJECT> 標籤載入 Applet,設定 ID="MyPlugin"。// Applet 端
import netscape.javascript.JSObject;
public class MyApplet extends Applet {
public void init() {
JSObject win = JSObject.getWindow(this); // 取得 window
JSObject doc = (JSObject) win.getMember("document"); // 取得 document
win.call("callCellMethod", new Object[]{"SetCellString",
new Object[]{new Integer(1), new Integer(1), new Integer(0), "Hello Cell"}});
}
}
<script language="JavaScript">
function callCellMethod(methodName, params) {
// 取得隱藏的 Cell 控件
var cell = document.all("DCellWeb1");
// 動態呼叫 Cell 方法
return cell[methodName].apply(cell, params);
}
</script>
<OBJECT classid="clsid:3F166327-8030-4881-8BD2-EA25350E574A"
id="DCellWeb1" style="HEIGHT: 0px; WIDTH: 0px">
<PARAM NAME="_Version" VALUE="65536">
<PARAM NAME="_ExtentX" VALUE="14902">
<PARAM NAME="_ExtentY" VALUE="6075">
<PARAM NAME="_StockProps" VALUE="0">
</OBJECT>
<!-- Applet OBJECT 標籤需有 ID -->
<OBJECT ID="MyPlugin" ...> ... </OBJECT>
<input type="button" value="觸發 Applet"
onClick="document.MyPlugin.appletMethod()" />
Applet 需宣告 public void appletMethod(),JavaScript 直接呼叫 document.MyPlugin.appletMethod()。
[Client Browser]
├─ Java Applet (UI, Business Logic)
│ │ JSObject.call("callCellMethod", ...)
│ ▼
├─ JavaScript Bridge (callCellMethod -> cell.SetCellString)
│ │
│ ▼
├─ Cell ActiveX (Hidden) --> Print Preview / Print / Export Excel
│
└─ Servlet / EJB (Backend Data)
public class BridgeApplet extends JApplet {
private JSObject win, cell;
public Object callCellMethod(String name, Object[] params) {
return getCell().call(name, params);
}
public Object callJavaScript(String name, Object[] params) {
return getJSWin().call(name, params);
}
private JSObject getCell() {
if (cell == null) {
JSObject doc = (JSObject) getJSWin().getMember("document");
JSObject all = (JSObject) doc.getMember("all");
cell = (JSObject) all.call("item", new Object[]{"DCellWeb1"});
}
return cell;
}
private JSObject getJSWin() {
if (win == null) win = JSObject.getWindow(this);
return win;
}
}
業務 Applet 繼承 BridgeApplet,即可直接呼叫 callCellMethod("SetCellString", new Object[]{col, row, page, value})。
| 優點 | 缺點 |
|---|---|
| 複雜報表排版零代碼(Cell 類 Excel 介面設計) | 僅限 Windows + IE(ActiveX 架構) |
| Applet 專注業務,列印邏輯完全外包 | 客戶端需安裝 OCX,簽名與安全策略維護成本高 |
| 支援匯出 Excel/PDF/圖片多種格式 | Java Applet 已被瀏覽器淘汰(Chrome 45+ 移除 NPAPI) |
print.js / html2canvas / jspdf 客戶端生成 PDF 列印。window.print() 或下載。「Applet + JavaScript + ActiveX」是早期企業級 Web 系統跨技術整合的典型模式。核心在於 netscape.javascript.JSObject 打通 Java ↔ JavaScript,再由 JavaScript 操作 DOM 中的 ActiveX 物件。雖技術棧已過時,但「表現與資料分離」、「輕量級橋接器」、「專業工具做專業事」的架構思想仍值得借鑑。