傳統 JSP 開發模式存在代碼與標記混雜、邏輯分散、調試困難、前後端強耦合等痛點。本文提出基於「統一 Servlet 控制器 + 業務 Bean 產出 XML + XSLT 轉換輸出」的管道架構,利用 JDK 1.4+ 內建 XML/XSLT API 與 IE6+ 客戶端原生支援,實現真正的「數據與表現分離」、多端適配、高度復用與標準化開發。
HTTP Request
↓
統一 Servlet (Front Controller)
├── URL 映射 → 業務 Bean (Action/Command 模式)
├── 業務 Bean 執行邏輯,**純粹產出 XML 數據** (DOM/SAX/序列化)
├── Servlet 根據請求參數/用戶代理 選擇 XSLT 樣式表
├── XSLT 處理器 轉換 XML → HTML / WML / SVG / PDF (XSL-FO) / JSON...
└── HTTP Response (Content-Type 對應輸出格式)
| 優勢維度 | 具體表現 | 業務價值 |
|---|---|---|
| 接口可視化、契約化 | 預先設計 Demo XML,前後端並行開發,程序員輸出驗證 XML Schema,美工基於 Demo XML 編寫 XSLT | 消除聯調階段,並行效率提升 50%+ |
| 美工零環境依賴 | 美工僅需瀏覽器 (IE6+/現代瀏覽器) 打開 Demo XML + XSLT 即時預覽效果,無需啟動 Servlet 容器 | 前端開發完全脫離後端環境 |
| 程序員驗證簡單 | 僅需文本比對輸出 XML 是否符合 Schema,無需渲染頁面檢查 | 單元測試覆蓋率易達 90%+ |
| 高度結構化復用 | XSLT 模板化編程 (` | 維護成本降低 60%,全站風格統一 |
| 多端適配零代碼修改 | 同一 XML 數據,配置不同 XSLT:Web (HTML)、手機 (WML/HTML5)、PDA、PDF (XSL-FO)、RSS、API (JSON) | 響應新終端需求只需增 XSLT,業務邏輯零修改 |
| 利用數據庫原生 XML | SQL Server 2000+ `FOR XML AUTO`、Oracle `XMLType`、PostgreSQL `xml` 類型,直接生成 XML 省去中間轉換層 | 數據層到表現層無縫銜接,性能提升 |
public class PipelineServlet extends HttpServlet {
private Map mappings; // URI → {beanClass, xsltPath}
private TransformerFactory tFactory = TransformerFactory.newInstance();
private Map xsltCache = new ConcurrentHashMap<>();
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
process(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
process(req, resp);
}
private void process(HttpServletRequest req, HttpServletResponse resp) {
String uri = req.getRequestURI();
PipelineMapping mapping = mappings.get(uri);
if (mapping == null) { resp.sendError(404); return; }
try {
// 1. 實例化/獲取 Bean (可整合 Spring/容器)
BusinessBean bean = (BusinessBean) Class.forName(mapping.beanClass).newInstance();
// 2. 執行業務邏輯,產出 XML (DOM Document)
Document xmlDoc = bean.execute(req); // 返回 org.w3c.dom.Document
// 3. 選擇 XSLT (可根據 User-Agent 動態選擇)
String xsltPath = selectXSLT(req, mapping);
// 4. 獲取/編譯 Templates
Templates templates = xsltCache.computeIfAbsent(xsltPath, p -> {
try { return tFactory.newTemplates(new StreamSource(getServletContext().getResourceAsStream(p))); }
catch (Exception e) { throw new RuntimeException(e); }
});
// 5. 轉換輸出
Transformer transformer = templates.newTransformer();
transformer.setParameter("contextPath", req.getContextPath()); // 傳遞上下文參數
transformer.transform(new DOMSource(xmlDoc), new StreamResult(resp.getOutputStream()));
} catch (Exception e) {
log("Pipeline error", e);
resp.sendError(500);
}
}
}
public class ProductListBean implements BusinessBean {
public Document execute(HttpServletRequest req) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc = dbf.newDocumentBuilder().newDocument();
Element root = doc.createElement("catalog");
doc.appendChild(root);
root.setAttribute("timestamp", new Date().toString());
List products = productDao.findAll(); // 純業務邏輯
for (Product p : products) {
Element item = doc.createElement("product");
item.setAttribute("id", String.valueOf(p.getId()));
item.appendChild(createElement(doc, "name", p.getName()));
item.appendChild(createElement(doc, "price", String.valueOf(p.getPrice())));
item.appendChild(createElement(doc, "image", p.getImageUrl()));
root.appendChild(item);
}
return doc;
}
private Element createElement(Document doc, String name, String text) {
Element e = doc.createElement(name);
e.setTextContent(text);
return e;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="https://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" indent="yes"/>
<xsl:template match="/catalog">
<html><head><title>產品目錄</title></head><body>
<h1>產品列表 (更新於: <xsl:value-of select="@timestamp"/>)</h1>
<table border="1">
<tr><th>名稱</th><th>價格</th><th>圖片</th></tr>
<xsl:for-each select="product">
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="price"/></td>
<td><img src="{image}" width="100"/></td>
</tr>
</xsl:for-each>
</table>
</body></html>
</xsl:template>
</xsl:stylesheet>
雖然現代框架(Spring MVC、Struts2、JSF、Thymeleaf、React/Vue+API)已主流,但 **「統一入口 + 數據模型 + 視圖模板」的管道思想始終未變**。XML+XSLT 方案在以下場景仍具獨特優勢:
理解這一架構,有助於看透現代框架的本質,在技術選型時不被表象迷惑。