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

JAXB 實戰指南:XML 與 Java 對象雙向轉換、核心註解詳解與最佳實踐

     編輯:Java 綜合教學

JAXB 核心三大件

  • JAXBContext:線程安全、重量級入口,緩存綁定元數據,建議單例復用。
  • Marshaller:Java 對象 → XML(序列化)。
  • Unmarshaller:XML → Java 對象(反序列化)。

常用映射註解速查表

完整實戰示例

1. 實體類定義

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "employee")
@XmlType(propOrder = {"name", "age", "role", "gender"})
public class Employee {
    @XmlAttribute(name = "id") // 映射為屬性
    private Long id;

    @XmlElement(name = "fullName") // 映射為元素,自定義名稱
    private String name;

    private int age;
    private String role;
    private String gender;

    // getter/setter/toString 省略...
}

2. XML 樣例

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employee id="1">
  <fullName>Pankaj</fullName>
  <age>29</age>
  <role>Java Developer</role>
  <gender>Male</gender>
</employee>

3. 雙向轉換工具類

public class JaxbUtils {
    // 緩存 Context,避免重複創建開銷
    private static final Map<Class<?>, JAXBContext> CONTEXT_CACHE = new ConcurrentHashMap<>();

    public static <T> String toXml(T obj, String encoding) {
        try {
            JAXBContext ctx = getContext(obj.getClass());
            Marshaller m = ctx.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 換行縮進
            m.setProperty(Marshaller.JAXB_ENCODING, encoding);
            StringWriter sw = new StringWriter();
            m.marshal(obj, sw);
            return sw.toString();
        } catch (JAXBException e) {
            throw new RuntimeException("XML 序列化失敗", e);
        }
    }

    public static <T> T fromXml(String xml, Class<T> clazz) {
        try {
            JAXBContext ctx = getContext(clazz);
            Unmarshaller um = ctx.createUnmarshaller();
            return clazz.cast(um.unmarshal(new StringReader(xml)));
        } catch (JAXBException e) {
            throw new RuntimeException("XML 反序列化失敗", e);
        }
    }

    private static JAXBContext getContext(Class<?> clazz) {
        return CONTEXT_CACHE.computeIfAbsent(clazz, c -> {
            try { return JAXBContext.newInstance(c); }
            catch (JAXBException e) { throw new RuntimeException(e); }
        });
    }
}

4. 測試驗證

@Test
public void roundTripTest() {
    // 對象 → XML
    Employee emp = new Employee();
    emp.setId(1L);
    emp.setName("Jane");
    emp.setAge(10);
    emp.setRole("Teacher");
    emp.setGender("Male");

    String xml = JaxbUtils.toXml(emp, "UTF-8");
    System.out.println(xml);
    // 輸出含換行縮進的完整 XML

    // XML → 對象
    Employee parsed = JaxbUtils.fromXml(xml, Employee.class);
    assertEquals(emp.getName(), parsed.getName());
    assertEquals(emp.getAge(), parsed.getAge());
}

進階技巧與避坑

  • 命名空間處理:@XmlSchema(namespace = "https://example.com", elementFormDefault = XmlNsForm.QUALIFIED) 於 package-info.java 定義。
  • 集合包裝:@XmlElementWrapper(name = "employees") @XmlElement(name = "employee") List<Employee> list; 生成雙層結構。
  • 日期/時間類型:JAXB 不原生支援 Java 8 LocalDate,需編寫 XmlAdapter<String, LocalDate> 配合 @XmlJavaTypeAdapter。
  • 大文件流式處理:JAXB 全量載入內存,超大 XML 請改用 StAX 或 SAX 流式解析。
  • 線程安全:Marshaller/Unmarshaller 非線程安全,每次轉換請 createMarshaller() 新建實例;JAXBContext 線程安全,務必緩存復用。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
註解作用對象核心屬性說明
@XmlRootElementClassname, namespace映射 XML 根元素,缺省類名
@XmlTypeClasspropOrder, name, namespace定義 XML Schema 類型與字段輸出順序
@XmlAccessorType(XmlAccessType.FIELD)ClassFIELD/PROPERTY/PUBLIC_MEMBER/NONEFIELD:直接綁定非 static/transient 字段(推薦,無需 getter)
@XmlElementField/Gettername, required, nillable, defaultValue映射 XML 子元素
@XmlAttributeField/Gettername, required映射 XML 屬性
@XmlElementWrapperCollection/Arrayname, nillable為集合生成外層包裝元素(如 <employees><employee/></employees>)
@XmlJavaTypeAdapterField/Class/Packagevalue (extends XmlAdapter)自定義序列化邏輯(如 LocalDate 格式化)
@XmlTransientField/Getter-忽略該字段,不參與綁定