現代電信與雲服務商廣泛採用 XML 定義服務實例配置(頻寬、配額、SLA 等),並透過 Web 入口網站或程式化 API 讓用戶自助變更。本文探討三種 XML 資料交換模式:伺服器序列化→網路傳輸→客戶端反序列化、檔案下載→本地解析修改→上傳同步、標準 Java 序列化 (XMLEncoder/XMLDecoder),並比較各模式優劣與適用場景。
public class ServiceInstance {
private String customerName;
private String packageName;
private String bandwidth; // 例:100Mbps, 1Gbps
private String downloadLimit; // 例:500GB
private int uptimeSLA; // 例:99.9
// Getter/Setter/Builder 略
}
適用於 Java-to-Java 內部通訊,無需外部依賴,但輸出格式為 JavaBeans 專屬 XML,非標準結構,跨語言互通性差。
import java.beans.XMLEncoder;
import java.io.*;
import java.net.*;
public class XmlEncoderServer {
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(8888);
System.out.println("伺服器啟動,等待連線...");
while (true) {
try (Socket client = server.accept();
OutputStream out = client.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(out)) {
// 建立服務實例
ServiceInstance svc = new ServiceInstance();
svc.setCustomerName("Josephine Bloggs");
svc.setPackageName("Internet");
svc.setBandwidth("1Gbps");
svc.setDownloadLimit("500GB");
svc.setUptimeSLA(99.9);
// XMLEncoder 序列化
XMLEncoder encoder = new XMLEncoder(bos);
encoder.writeObject(svc);
encoder.close(); // 關鍵:flush 並寫入結束標籤
System.out.println("已傳送服務定義至客戶端");
}
}
}
}
import java.beans.XMLDecoder;
import java.io.*;
import java.net.*;
public class XmlDecoderClient {
public static void main(String[] args) throws Exception {
try (Socket socket = new Socket("localhost", 8888);
InputStream in = socket.getInputStream();
BufferedInputStream bis = new BufferedInputStream(in)) {
XMLDecoder decoder = new XMLDecoder(bis);
ServiceInstance svc = (ServiceInstance) decoder.readObject();
decoder.close();
System.out.println("接收到服務定義:");
System.out.println("客戶: " + svc.getCustomerName());
System.out.println("方案: " + svc.getPackageName());
System.out.println("頻寬: " + svc.getBandwidth());
System.out.println("下載限額: " + svc.getDownloadLimit());
System.out.println("SLA: " + svc.getUptimeSLA() + "%");
// 本地修改頻寬
svc.setBandwidth("10Gbps");
System.out.println("\n本地修改頻寬為: " + svc.getBandwidth());
// 回傳更新(實務上需建立新連線或雙向通訊)
}
}
}
使用標準結構 XML,配合 dom4j、JDOM 或 JAXB 解析,適合異構系統整合。
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import java.io.*;
import java.net.*;
public class StandardXmlServer {
public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(8889);
while (true) {
try (Socket client = server.accept();
OutputStream out = client.getOutputStream()) {
// 建立標準 XML 結構
Element root = new Element("ServiceInstance");
root.addContent(new Element("Customer").setText("Josephine Bloggs"));
root.addContent(new Element("Package").setText("Internet"));
root.addContent(new Element("Bandwidth").setText("1Gbps"));
root.addContent(new Element("DownloadLimit").setText("500GB"));
root.addContent(new Element("Uptime").setText("99.9"));
Document doc = new Document(root);
// 輸出到 Socket
XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
outputter.output(doc, out);
out.flush();
}
}
}
}
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.*;
import java.net.*;
import java.util.List;
public class Dom4jClient {
public static void main(String[] args) throws Exception {
try (Socket socket = new Socket("localhost", 8889);
InputStream in = socket.getInputStream()) {
SAXReader reader = new SAXReader();
Document doc = reader.read(in);
Element root = doc.getRootElement();
// 讀取資料
String customer = root.elementText("Customer");
String bandwidth = root.elementText("Bandwidth");
System.out.println("原始頻寬: " + bandwidth);
// 修改頻寬
Element bwElem = root.element("Bandwidth");
bwElem.setText("10Gbps");
System.out.println("修改後頻寬: " + bwElem.getText());
// 序列化回字串(可傳回伺服器)
String updatedXml = doc.asXML();
System.out.println("\n更新後 XML:\n" + updatedXml);
}
}
}
適用於用戶透過瀏覽器下載 XML 設定檔、本地編輯後上傳同步的場景。
jakarta.xml.bind
jakarta.xml.bind-api
4.0.0
org.glassfish.jaxb
jaxb-runtime
4.0.0
import jakarta.xml.bind.annotation.*;
@XmlRootElement(name = "ServiceInstance")
@XmlAccessorType(XmlAccessType.FIELD)
public class ServiceInstanceJaxb {
@XmlElement(name = "Customer")
private String customerName;
@XmlElement(name = "Package")
private String packageName;
@XmlElement(name = "Bandwidth")
private String bandwidth;
@XmlElement(name = "DownloadLimit")
private String downloadLimit;
@XmlElement(name = "Uptime")
private double uptimeSLA;
// Getter/Setter
}
import jakarta.xml.bind.*;
import java.io.File;
public class JaxbFileDemo {
public static void main(String[] args) throws Exception {
JAXBContext ctx = JAXBContext.newInstance(ServiceInstanceJaxb.class);
// 1. 寫入檔案 (Marshalling)
ServiceInstanceJaxb svc = new ServiceInstanceJaxb();
svc.setCustomerName("Josephine Bloggs");
svc.setPackageName("Internet");
svc.setBandwidth("1Gbps");
svc.setDownloadLimit("500GB");
svc.setUptimeSLA(99.9);
Marshaller marshaller = ctx.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.marshal(svc, new File("service_config.xml"));
System.out.println("已寫入 service_config.xml");
// 2. 讀取檔案 (Unmarshalling)
Unmarshaller unmarshaller = ctx.createUnmarshaller();
ServiceInstanceJaxb loaded = (ServiceInstanceJaxb) unmarshaller.unmarshal(new File("service_config.xml"));
System.out.println("讀取客戶: " + loaded.getCustomerName());
// 3. 修改並寫回
loaded.setBandwidth("10Gbps");
marshaller.marshal(loaded, new File("service_config.xml"));
System.out.println("已更新頻寬至 10Gbps");
}
}
| 維度 | XMLEncoder/Decoder | 標準 XML + dom4j/JDOM | JAXB (標準 XML) |
|---|---|---|---|
| 跨語言互通 | ❌ 僅 Java | ✅ 任意語言 | ✅ 任意語言 |
| XML 結構控制 | ❌ 固定 JavaBeans 格式 | ✅ 完全自訂 | ✅ 註解控制 |
| Schema 驗證 | ❌ 無 | ✅ 可整合 XSD | ✅ 內建支援 |
| 開發效率 | ⭐⭐⭐ 零配置 | ⭐⭐ 手動映射 | ⭐⭐⭐ 註解驅動 |
| 效能/記憶體 | 中等 | 中等 (DOM 模式) | 中等 |
| 適用場景 | Java 內部 RMI/序列化 | 異構整合、舊系統對接 | 現代企業應用標準選擇 |
XML 作為服務定義的資料交換格式,在電信、金融、企業整合領域仍具不可替代地位。Java 提供了從零依賴的 XMLEncoder 到標準化的 JAXB、靈活的 dom4j/JDOM 多層次工具鏈。現代架構建議:對外介面採用標準 XML + JAXB/JDOM + Schema 驗證 + REST/gRPC 傳輸;內部 Java 服務間若追求極簡開發,可考慮 XMLEncoder。核心原則是「契約優先,工具次之」,以 XSD 定義穩定契約,再選擇適合團隊技術棧的綁定框架。