首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java XML 解析四大技術全景對比:DOM、SAX、StAX、JAXB 選型指南

     編輯:Java 程式設計入門

四大解析技術定位速查

技術模式記憶體速度API 風格適用場景
DOM樹模型高(全量載入)中隨機存取小型 XML、需頻繁修改/回寫
SAX事件推送極低(流式)快回調/訪問者大型 XML、單向讀取、記憶體受限
StAX拉取流低(流式)快迭代器/游標大型 XML、需主動控制解析節奏
JAXB物件綁定中(視物件圖)中註解驅動 POJO業務導向、Schema 穩定、序列化/反序列化

SAX 實戰:事件驅動解析配置檔

適用於結構固定、單向讀取的大型配置 XML。核心繼承 DefaultHandler,覆寫三大回調:

public class ConfigParser extends DefaultHandler {
    private String currentSection;
    public SysConfigItem sysConfig;
    public List<InterfaceConfigItem> interfaces = new ArrayList<>();
    // ... 其他列表

    @Override public void startDocument() { /* 初始化容器 */ }

    @Override public void startElement(String uri, String local, String qName, Attributes attrs) {
        if ("Item".equalsIgnoreCase(qName) && attrs.getLength() > 0) {
            switch (currentSection) {
                case "SysConfigItem": sysConfig = new SysConfigItem(attrs); break;
                case "InterfaceConfigItems": interfaces.add(new InterfaceConfigItem(attrs)); break;
                // ...
            }
        } else {
            currentSection = qName; // 記錄當前父元素
        }
    }
    // endElement、characters 視需求實作
}

配合反射基底類別 ConfigItemBase,可自動將 Attributes 映射至欄位(支援 String/Integer/Double/Date),極大減少樣板碼。

JAXB 實戰:複雜業務報文自動綁定

針對巢狀深、欄位多、含 CDATA 夾帶內層 XML 的電信 B2B 報文(如 BatchSyncOrderRelationReq),JAXB 表現最優。

外層報文頭解析

@XmlRootElement(name = "InterBOSS")
@XmlAccessorType(XmlAccessType.FIELD)
public class MessageHead {
    @XmlElement(name = "Version") String version;
    @XmlElement(name = "BIPType") BIPType bipType;
    @XmlElement(name = "SvcCont") String svcCont; // CDATA 內容原樣保留
    // getter/setter
}

內層業務體綁定

@XmlRootElement(name = "batchSyncOrderRelationReq")
@XmlAccessorType(XmlAccessType.FIELD)
public class BatchSyncOrderRelationReq extends BossMessage<BatchSyncOrderRelationReq> {
    @XmlElement(name = "msgTransactionID") String msgTransactionId;
    @XmlElement(name = "reqNum") String reqNum;
    @XmlElement(name = "reqBody") List<ReqBody> reqBodyList;

    @Override
    public BatchSyncOrderRelationReq Deserialized(String interBossXml) throws BusinessException {
        try {
            // 1. 解析外層頭
            JAXBContext headCtx = JAXBContext.newInstance(MessageHead.class);
            MessageHead head = (MessageHead) headCtx.createUnmarshaller()
                    .unmarshal(new StringReader(interBossXml));

            // 2. 解析 CDATA 內層 XML
            JAXBContext bodyCtx = JAXBContext.newInstance(BatchSyncOrderRelationReq.class);
            BatchSyncOrderRelationReq body = (BatchSyncOrderRelationReq) bodyCtx.createUnmarshaller()
                    .unmarshal(new StringReader(head.getSvcCont().trim()));

            body.setHead(head);
            return body;
        } catch (JAXBException e) {
            throw new BusinessException("反序列化失敗", e);
        }
    }
}

@XmlAccessorType(XmlAccessType.FIELD)
class ReqBody {
    @XmlElement(name = "oprNumb") String oprNumb;
    @XmlElement(name = "subscriptionInfo") SubscriptionInfo subInfo;
}

@XmlAccessorType(XmlAccessType.FIELD)
class SubscriptionInfo {
    @XmlElement(name = "oprTime") String oprTime;
    @XmlElement(name = "actionID") String actionId;
    @XmlElement(name = "brand") String brand;
    // ... 20+ 欄位皆以註解映射,零手寫解析邏輯
}

JAXB 進階技巧

  • @XmlJavaTypeAdapter:自訂型別轉換器(如 LocalDate ↔ String)
  • @XmlElementWrapper:為集合添加包裹元素
  • Marshaller.JAXB_FORMATTED_OUTPUT:序列化時美化縮排
  • 針對大型 XML 可搭配 StAXSource 進行分塊解析,避免全量載入

選型決策樹

  1. XML < 10MB 且需隨機存取/修改 → DOM
  2. XML > 100MB 或記憶體極度受限 → SAX(只讀)或 StAX(需雙向控制)
  3. 有 XSD Schema、業務物件模型穩定、需序列化/反序列化 → JAXB(首選)
  4. 無 Schema、臨時解析、一次性腳本 → DOM 或 XPath 最省事

效能基準參考(10MB XML,i7-12700H,JDK 17)

  • DOM 解析 + 遍歷:~450 ms,堆峰值 ~180 MB
  • SAX 解析 + 計數:~120 ms,堆峰值 ~5 MB
  • StAX 解析 + 計數:~110 ms,堆峰值 ~5 MB
  • JAXB 反序列化至 POJO:~200 ms,堆峰值 ~60 MB

實際專案中,JAXB 開發效率優勢通常遠超效能差異,除非極端高吞吐場景。

常見坑點

  • JAXB 需無參建構器,欄位若為 private 需配合 @XmlAccessorType(FIELD) 或提供 getter/setter
  • 命名空間處理:@XmlSchema(namespace = "...") + package-info.java
  • CDATA 內容若含特殊字元,確保 Marshaller.JAXB_ENCODING 設為 UTF-8
  • JDK 9+ 模組化後需額外引入 jaxb-api、jaxb-runtime 依賴
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved