JSP 作為視圖層,與 XML 數據交互主要有三種架構模式,按「關注點分離」程度遞增。本文對比三種模式的優劣、代碼結構與適用場景,指導選型。
<%@ page import="javax.xml.parsers.*,org.w3c.dom.*,java.io.*" %>
<%
// 讀取 XML 文件
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(application.getRealPath("/data/books.xml"));
NodeList list = doc.getElementsByTagName("book");
for (int i=0; i<list.getLength(); i++) {
Element e = (Element) list.item(i);
out.println("<li>" + e.getElementsByTagName("title").item(0).getTextContent() + "</li>");
}
%>
| 優點 | 缺點 |
|---|---|
| 零額外類,快速原型 | Java 代碼與 HTML 混雜,不可復用、難測試、難維護 |
| 適合一次性腳本 | 解析邏輯耦合在視圖,違反 MVC |
Bean 類 (com.example.BookCatalog):
public class BookCatalog {
private List<Book> books;
public void load(String xmlPath) { /* DOM/SAX/StAX 解析 */ }
public List<Book> getBooks() { return books; }
// 可加入 XSLT 轉換方法
public String transform(String xsltPath) { /* Transformer */ }
}
JSP 使用:
<jsp:useBean id="catalog" class="com.example.BookCatalog" scope="application" />
<jsp:setProperty name="catalog" property="xmlPath" value="/data/books.xml" />
<ul>
<c:forEach items="${catalog.books}" var="book">
<li>${book.title} - ${book.price}</li>
</c:forEach>
</ul>
| 優點 | 缺點 |
|---|---|
| 邏輯封裝在 Bean,可單測、可復用 | JSP 仍需知道 Bean 屬性名,耦合度中等 |
支援 <jsp:setProperty property="*"/> 自動綁定表單參數 | 複雜 XML 轉換邏輯(XSLT)在 Bean 內部仍顯笨重 |
| 可切換解析器實現(DOM/SAX/StAX)不影響 JSP | 大量 Bean 實例佔用 Session/Application 內存需注意 |
TLD 定義 (/WEB-INF/tld/xml.tld):
<taglib xmlns="https://java.sun.com/xml/ns/javaee" version="2.1">
<tlib-version>1.0</tlib-version>
<short-name>xml</short-name>
<uri>https://example.com/xml</uri>
<tag>
<name>parse</name>
<tag-class>com.example.tag.XmlParseTag</tag-class>
<body-content>empty</body-content>
<attribute><name>src</name><required>true</required><rtexprvalue>true</rtexprvalue></attribute>
<attribute><name>var</name><required>true</required></attribute>
<attribute><name>scope</name><required>false</required></attribute>
</tag>
<tag>
<name>transform</name>
<tag-class>com.example.tag.XmlTransformTag</tag-class>
<body-content>empty</body-content>
<attribute><name>xml</name><required>true</required></attribute>
<attribute><name>xslt</name><required>true</required></attribute>
<attribute><name>var</name><required>true</required></attribute>
</tag>
</taglib>
標簽處理類 (繼承 SimpleTagSupport):
public class XmlParseTag extends SimpleTagSupport {
private String src, var;
private int scope = PageContext.PAGE_SCOPE;
// setter...
@Override public void doTag() throws JspException, IOException {
Document doc = parseXml(src); // 解析邏輯
getJspContext().setAttribute(var, doc, scope);
}
}
JSP 極簡調用:
<%@ taglib prefix="x" uri="https://example.com/xml" %>
<x:parse src="/data/books.xml" var="doc" scope="request" />
<x:transform xml="${doc}" xslt="/xslt/book-list.xsl" var="html" />
${html} <!-- 直接輸出轉換後 HTML -->
| 維度 | 直接操作 | JavaBeans | 標簽庫 |
|---|---|---|---|
| 代碼分離度 | 極低 | 中 | **高** |
| 可測試性 | 難 | 易(單元測試 Bean) | 易(測試 Tag Handler) |
| 前端友好度 | 需懂 Java | 需懂 Bean API | **像寫 HTML 一樣寫標簽** |
| 復用性 | 無 | Bean 級 | **標簽級,跨專案可打包發布** |
| 學習成本 | 低 | 中 | 高(需掌握 Tag API、TLD) |
| 適用場景 | 原型、腳本、一次性任務 | 中小型項目、表單綁定、業務邏輯封裝 | 大型項目、組件化、設計師協作、框架開發 |
applicationContext.xml、web.xml → 逐漸被 Java Config / YAML 取代。結論:新項目**首選 JSON + REST**,XML 僅作為邊界適配格式。若必須在 JSP 處理 XML,**標簽庫模式提供最佳分離度**,但投入成本高;中小項目用 **JavaBeans + JSTL** 性價比最高;嚴禁在 JSP 腳本片段中直接寫 XML 解析代碼。