Aspire 是一個基於 XML/XSL、J2EE 與關聯式資料庫的 RAD (快速應用開發) 工具,可部署於 Tomcat、WebSphere 等 Servlet 容器。其核心概念層次資料集 (Hierarchical Data Set, HDS) 將關聯式資料轉換為樹狀結構,支援 XML、HTML、Excel、Java 物件等多格式輸出,極大簡化 MVC 架構下 Controller 與 View 的資料傳遞。
<AspireDataSet>
<!-- 根層 Key-Value -->
<key1>val1</key1>
<key2>val2</key2>
<!-- 迴圈 = 子資料表 -->
<loop name="orders">
<row>
<orderId>1001</orderId>
<customer>Acme Corp</customer>
<!-- 巢狀子迴圈 -->
<loop name="items">
<row><itemId>A1</itemId><qty>10</qty></row>
<row><itemId>B2</itemId><qty>5</qty></row>
</loop>
</row>
<row>...</row>
</loop>
</AspireDataSet>
loop 對應資料表/子查詢,row 為記錄,支援無限巢狀深度。
package com.ai.htmlgen;
public interface ihds extends ILoopForwardIterator {
ihds getParent(); // 取得父層 HDS
IIterator getChildNames(); // 取得子迴圈名稱列表
ihds getChild(String childName); // 取得指定子迴圈 HDS
String getAggregateValue(String key); // 取得彙總值 (SUM/AVG/COUNT)
IMetaData getMetaData(); // 取得欄位中繼資料
void close(); // 釋放資源
}
public interface ILoopForwardIterator {
String getValue(String key); // 取得當前行指定欄位值
void moveToFirst(); // 移至第一行
void moveToNext(); // 移至下一行
boolean isAtTheEnd(); // 是否已到末尾
}
public interface IMetaData {
IIterator getIterator(); // 欄位名稱迭代器
int getColumnCount(); // 欄位數
int getIndex(String attributeName); // 欄位索引
}
關鍵特性:非 DOM 實作,記憶體效率高;游標式前向迭代;遞迴巢狀存取。
###################################
# ihdsTest 資料定義
###################################
# 區段 1: 根 HDS 定義
request.ihdsTest.className=com.ai.htmlgen.DBHashTableFormHandler1
request.ihdsTest.loopNames=works
# 區段 2: works 迴圈 (主檔)
request.ihdsTest.works.class_request.className=com.ai.htmlgen.GenericTableHandler6
request.ihdsTest.works.loopNames=childloop1
request.ihdsTest.works.query_request.className=com.ai.data.RowFileReader
request.ihdsTest.works.query_request.filename=aspire:\\samples\\pop-table-tags\\properties\\pop-table.data
# 區段 3: childloop1 迴圈 (明細檔)
request.childloop1.class_request.className=com.ai.htmlgen.GenericTableHandler6
request.childloop1.query_request.className=com.ai.data.RowFileReader
request.childloop1.query_request.filename=aspire:\\samples\\pop-table-tags\\properties\\pop-table.data
| 類別 | 角色 |
|---|---|
| DBHashTableFormHandler1 | 根 HDS 建構器,將關聯式資料組裝為層次結構 |
| GenericTableHandler6 | 迴圈處理器,實作 ihds 介面,支援彙總、行數統計 |
| RowFileReader | 資料來源適配器:平面檔讀取器 |
| DBRequestExecutor2 | 資料來源適配器:SQL 查詢執行器 |
| StoredProcedureExecutor2 | 資料來源適配器:預存程序執行器 |
| XMLReader | 資料來源適配器:XML 檔案讀取器 |
資料來源適配器實作 IDataCollection 介面,可自行擴充。
Hashtable args = new Hashtable();
args.put("key1".toLowerCase(), "value1"); // 參數鍵值需小寫
IFactory factory = AppObjects.getFactory();
ihds hds = (ihds) factory.getObject("ihdsTest", args);
// 遞迴列印 HDS 結構
public static void staticTransform(ihds data, PrintWriter out) throws TransformException {
try { writeALoop("MainData", data, out, ""); }
catch (DataException x) { throw new TransformException("Error", x); }
}
private static void writeALoop(String loopName, ihds data, PrintWriter out, String indent) throws DataException {
println(out, indent, ">> Writing data for loop: " + loopName);
// 列印欄位名
IMetaData m = data.getMetaData();
IIterator cols = m.getIterator();
StringBuffer colBuf = new StringBuffer();
for (cols.moveToFirst(); !cols.isAtTheEnd(); cols.moveToNext()) {
colBuf.append(cols.getCurrentElement()).append("|");
}
println(out, indent, colBuf.toString());
// 列印資料行
for (data.moveToFirst(); !data.isAtTheEnd(); data.moveToNext()) {
StringBuffer rowBuf = new StringBuffer();
for (cols.moveToFirst(); !cols.isAtTheEnd(); cols.moveToNext()) {
rowBuf.append(data.getValue((String)cols.getCurrentElement())).append("|");
}
println(out, indent, rowBuf.toString());
// 遞迴處理子迴圈
IIterator children = data.getChildNames();
for (children.moveToFirst(); !children.isAtTheEnd(); children.moveToNext()) {
String childName = (String) children.getCurrentElement();
writeALoop(childName, data.getChild(childName), out, indent + "\t");
}
}
println(out, indent, ">> Writing data for loop: " + loopName + " is complete");
}
###################################
# ihdsTestURL: URL 映射
###################################
ihdsTestURL=aspire:\\samples\\ihds-test\\ihds-default-html-template.html
ihdsTestURL.formHandlerName=ihdsTest
request.ihdsTest.form_handler.class_request.className=com.ai.htmlgen.DBHashTableFormHandler1
# XML 輸出
GenericTransform.Classic-xml.classname=com.ai.xml.FormHandlerToXMLTransform
GenericTransform.Object-xml.classname=com.ai.generictransforms.ObjectXMLGenericTransform
# Excel 輸出
GenericTransform.Excel.classname=com.ai.generictransforms.ExcelGenericTransform
# 文字輸出
GenericTransform.Text.classname=com.ai.generictransforms.DebugTextTransform
# HTML (預設模板)
https://host:port/webapp/servlet/DisplayServlet?url=ihdsTestURL
# 標準 XML
https://host:port/webapp/servlet/DisplayServlet?url=ihdsTestURL&aspire_output_format=classic-xml
# Excel
https://host:port/webapp/servlet/DisplayServlet?url=ihdsTestURL&aspire_output_format=Excel
# 純文字
https://host:port/webapp/servlet/DisplayServlet?url=ihdsTestURL&aspire_output_format=Text
package com.ai.generictransforms;
public class ExcelGenericTransform extends AHttpGenericTransform implements IFormHandlerTransform {
private static String s_separator = "\t";
protected String getDerivedHeaders(HttpServletRequest request) {
return "Content-Type=application/vnd.ms-excel|Content-Disposition=filename=aspire-hierarchical-dataset.xls";
}
public void transform(ihds data, PrintWriter out) throws TransformException {
staticTransform(data, out);
}
// staticTransform 邏輯同前,以 tab 分隔輸出
}
| 受益角色 | 價值 |
|---|---|
| 前端開發者 | 頁面模板只需放置標籤,無需撰寫資料存取邏輯 |
| B2B 整合 | 直接輸出標準 XML,支援系統間資料交換 |
| 報表使用者 | 一鍵匯出 Excel,免開發報表程式 |
| Java 開發者 | 取得 ihds 物件直接操作,類似 DOM 但更輕量 |
| 學習者 | 免費、輕量、整合 Tomcat+資料庫+XML+XSL,完整 J2EE 學習階梯 |
Aspire/HDS 概念對應現代技術:
雖 Aspire 專案已不活躍,但其「單一資料結構多重表現」的架構思想在現代 API 設計、微服務資料聚合、報表系統中仍具指導意義。