| 技術 | 模式 | 記憶體 | 速度 | API 風格 | 適用場景 |
|---|---|---|---|---|---|
| DOM | 樹模型 | 高(全量載入) | 中 | 隨機存取 | 小型 XML、需頻繁修改/回寫 |
| SAX | 事件推送 | 極低(流式) | 快 | 回調/訪問者 | 大型 XML、單向讀取、記憶體受限 |
| StAX | 拉取流 | 低(流式) | 快 | 迭代器/游標 | 大型 XML、需主動控制解析節奏 |
| JAXB | 物件綁定 | 中(視物件圖) | 中 | 註解驅動 POJO | 業務導向、Schema 穩定、序列化/反序列化 |
適用於結構固定、單向讀取的大型配置 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),極大減少樣板碼。
針對巢狀深、欄位多、含 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+ 欄位皆以註解映射,零手寫解析邏輯
}
@XmlJavaTypeAdapter:自訂型別轉換器(如 LocalDate ↔ String)@XmlElementWrapper:為集合添加包裹元素Marshaller.JAXB_FORMATTED_OUTPUT:序列化時美化縮排StAXSource 進行分塊解析,避免全量載入實際專案中,JAXB 開發效率優勢通常遠超效能差異,除非極端高吞吐場景。
private 需配合 @XmlAccessorType(FIELD) 或提供 getter/setter@XmlSchema(namespace = "...") + package-info.javaMarshaller.JAXB_ENCODING 設為 UTF-8jaxb-api、jaxb-runtime 依賴