最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

javax.xml.bind.JAXBContext操作XML的實(shí)現(xiàn)示例

 更新時(shí)間:2025年12月03日 10:07:11   作者:隔壁阿布都  
JAXB是Java標(biāo)準(zhǔn)API,用于Java對(duì)象與XML的相互轉(zhuǎn)換,通過注解定義映射規(guī)則,本文就來詳細(xì)的介紹一下javax.xml.bind.JAXBContext操作XML的實(shí)現(xiàn),感興趣的可以了解一下

JAXB(Java Architecture for XML Binding)是 Java 標(biāo)準(zhǔn) API(JDK 1.6+ 內(nèi)置,JDK 9+ 需手動(dòng)引入依賴),用于實(shí)現(xiàn) Java 對(duì)象與 XML 文檔的相互轉(zhuǎn)換(序列化/反序列化)。核心類 JAXBContext 負(fù)責(zé)管理 XML 與 Java 類型的綁定關(guān)系,配合 Marshaller(對(duì)象轉(zhuǎn) XML)和 Unmarshaller(XML 轉(zhuǎn)對(duì)象)完成核心操作。

一、前置準(zhǔn)備(依賴說明)

1. JDK 版本差異

  • JDK 8 及以下:JAXB 是 JDK 內(nèi)置模塊(javax.xml.bind),無需額外依賴。
  • JDK 9 及以上:JAXB 被移除出默認(rèn)模塊(模塊化改革),需手動(dòng)引入 Maven/Gradle 依賴(遷移到 Jakarta EE 后包名不變,但需指定依賴):

Maven 依賴(JDK 9+)

<!-- JAXB 核心依賴 -->
<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>2.3.3</version>
</dependency>
<!-- 運(yùn)行時(shí)實(shí)現(xiàn)(必須,否則報(bào)錯(cuò) ClassNotFoundException) -->
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.3</version>
    <scope>runtime</scope>
</dependency>
<!-- 用于 JDK 9+ 模塊支持(可選,解決模塊訪問限制) -->
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.3.3</version>
</dependency>

Gradle 依賴(JDK 9+)

implementation 'jakarta.xml.bind:jakarta.xml.bind-api:2.3.3'
runtimeOnly 'com.sun.xml.bind:jaxb-impl:2.3.3'
runtimeOnly 'com.sun.xml.bind:jaxb-core:2.3.3'

二、核心注解說明(Java 實(shí)體 → XML 映射)

JAXB 通過注解定義 Java 類與 XML 元素的映射規(guī)則,常用注解如下:

注解作用場景說明
@XmlRootElement類級(jí)別標(biāo)記該類為 XML 根元素(必須,否則無法序列化),可指定 name(XML 根節(jié)點(diǎn)名)
@XmlElement字段/ getter 方法映射 Java 字段到 XML 子元素,可指定 name(XML 子節(jié)點(diǎn)名)、required(是否必選)
@XmlAttribute字段/ getter 方法映射 Java 字段到 XML 元素的屬性(而非子元素)
@XmlTransient字段/ getter 方法忽略該字段(不參與 XML 序列化/反序列化)
@XmlAccessorType類級(jí)別指定字段訪問策略(如 FIELD:直接訪問字段,無需 getter/setter)
@XmlList集合字段將集合元素序列化為 XML 單個(gè)元素的多個(gè)值(用空格分隔)
@XmlRootElement類級(jí)別根元素注解,必須存在

三、完整使用步驟(示例驅(qū)動(dòng))

場景:實(shí)現(xiàn)User類與 XML 的相互轉(zhuǎn)換,包含嵌套對(duì)象、集合、屬性

步驟 1:定義 Java 實(shí)體類(帶 JAXB 注解)

import javax.xml.bind.annotation.*;
import java.util.List;

// 根元素:XML 根節(jié)點(diǎn)名為 <user>
@XmlRootElement(name = "user")
// 訪問策略:直接操作字段(無需 getter/setter,簡化代碼)
@XmlAccessorType(XmlAccessType.FIELD)
public class User {

    // XML 元素的屬性:<user id="1001">
    @XmlAttribute(name = "id")
    private Long userId;

    // XML 子元素:<username>張三</username>(必選)
    @XmlElement(name = "username", required = true)
    private String name;

    // XML 子元素:<age>25</age>
    @XmlElement
    private Integer age;

    // 嵌套對(duì)象(XML 子元素嵌套)
    @XmlElement(name = "address")
    private Address address;

    // 集合字段(XML 子元素:<hobbies>籃球 足球</hobbies>)
    @XmlElement(name = "hobbies")
    @XmlList // 集合元素序列化為單個(gè)元素的多個(gè)值
    private List<String> hobbies;

    // 忽略該字段(不生成 XML 元素)
    @XmlTransient
    private String password;

    // 嵌套類(地址信息)
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class Address {
        @XmlElement(name = "province")
        private String province;
        @XmlElement(name = "city")
        private String city;

        // 必須有默認(rèn)無參構(gòu)造器(JAXB 反射創(chuàng)建對(duì)象時(shí)需要)
        public Address() {}
        public Address(String province, String city) {
            this.province = province;
            this.city = city;
        }

        // getter/setter(可選,因使用 FIELD 訪問策略)
        // ...
    }

    // 必須有默認(rèn)無參構(gòu)造器(JAXB 強(qiáng)制要求)
    public User() {}

    // 帶參構(gòu)造器(方便創(chuàng)建對(duì)象)
    public User(Long userId, String name, Integer age, Address address, List<String> hobbies) {
        this.userId = userId;
        this.name = name;
        this.age = age;
        this.address = address;
        this.hobbies = hobbies;
    }

    // getter/setter(可選,若需外部操作字段)
    // ...
}

關(guān)鍵注意:

  1. 所有參與序列化的類(包括嵌套類)必須有 默認(rèn)無參構(gòu)造器(JAXB 反射實(shí)例化需要)。
  2. 注解可加在字段或 getter 方法上,建議統(tǒng)一風(fēng)格(如示例用 XmlAccessType.FIELD 直接操作字段)。

步驟 2:Java 對(duì)象 → XML(序列化,Marshaller)

核心流程:

  1. 通過 JAXBContext.newInstance(Class...) 創(chuàng)建上下文(指定要綁定的 Java 類)。
  2. 從上下文獲取 Marshaller 實(shí)例。
  3. 配置 Marshaller(如格式化輸出、編碼、忽略XML聲明等)。
  4. 調(diào)用 marshall() 方法序列化(輸出到文件、流、字符串等)。

示例代碼:對(duì)象轉(zhuǎn) XML 文件/字符串

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.io.File;
import java.io.StringWriter;
import java.util.Arrays;

public class JaxbMarshallerDemo {
    public static void main(String[] args) {
        // 1. 創(chuàng)建 Java 對(duì)象(模擬數(shù)據(jù))
        User.Address address = new User.Address("廣東省", "深圳市");
        User user = new User(
            1001L,
            "張三",
            25,
            address,
            Arrays.asList("籃球", "足球", "編程")
        );

        try {
            // 2. 創(chuàng)建 JAXBContext(參數(shù)為要綁定的實(shí)體類)
            JAXBContext context = JAXBContext.newInstance(User.class);

            // 3. 獲取 Marshaller 實(shí)例(負(fù)責(zé)序列化)
            Marshaller marshaller = context.createMarshaller();

            // 4. 配置 Marshaller
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 格式化輸出(換行、縮進(jìn))
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); // 編碼格式
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false); // 是否省略 XML 聲明(<?xml ...?>)

            // 5. 序列化到 XML 文件
            File xmlFile = new File("user.xml");
            marshaller.marshal(user, xmlFile);
            System.out.println("XML 文件已生成:" + xmlFile.getAbsolutePath());

            // 6. 序列化到字符串(便于網(wǎng)絡(luò)傳輸?shù)葓鼍埃?
            StringWriter writer = new StringWriter();
            marshaller.marshal(user, writer);
            String xmlStr = writer.toString();
            System.out.println("\nXML 字符串:");
            System.out.println(xmlStr);

        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}

生成的 XML 文件(user.xml)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user id="1001">
    <username>張三</username>
    <age>25</age>
    <address>
        <province>廣東省</province>
        <city>深圳市</city>
    </address>
    <hobbies>籃球 足球 編程</hobbies>
</user>

步驟 3:XML → Java 對(duì)象(反序列化,Unmarshaller)

核心流程:

  1. 同樣通過 JAXBContext.newInstance(Class...) 創(chuàng)建上下文。
  2. 從上下文獲取 Unmarshaller 實(shí)例。
  3. 調(diào)用 unmarshal() 方法反序列化(從文件、流、字符串讀取 XML)。

示例代碼:XML 文件/字符串轉(zhuǎn)對(duì)象

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.io.StringReader;

public class JaxbUnmarshallerDemo {
    public static void main(String[] args) {
        try {
            // 1. 創(chuàng)建 JAXBContext
            JAXBContext context = JAXBContext.newInstance(User.class);

            // 2. 獲取 Unmarshaller 實(shí)例(負(fù)責(zé)反序列化)
            Unmarshaller unmarshaller = context.createUnmarshaller();

            // 3. 從 XML 文件反序列化到對(duì)象
            File xmlFile = new File("user.xml");
            User userFromFile = (User) unmarshaller.unmarshal(xmlFile);
            System.out.println("從文件解析的 User:");
            System.out.println("用戶ID:" + userFromFile.getUserId());
            System.out.println("姓名:" + userFromFile.getName());
            System.out.println("地址:" + userFromFile.getAddress().getProvince() + "-" + userFromFile.getAddress().getCity());
            System.out.println("愛好:" + userFromFile.getHobbies());

            // 4. 從 XML 字符串反序列化到對(duì)象
            String xmlStr = """
                <?xml version="1.0" encoding="UTF-8"?>
                <user id="1002">
                    <username>李四</username>
                    <age>30</age>
                    <address>
                        <province>浙江省</province>
                        <city>杭州市</city>
                    </address>
                    <hobbies>讀書 旅行</hobbies>
                </user>
                """;
            StringReader reader = new StringReader(xmlStr);
            User userFromStr = (User) unmarshaller.unmarshal(reader);
            System.out.println("\n從字符串解析的 User:");
            System.out.println("用戶ID:" + userFromStr.getUserId());
            System.out.println("姓名:" + userFromStr.getName());

        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}

輸出結(jié)果

從文件解析的 User:
用戶ID:1001
姓名:張三
地址:廣東省-深圳市
愛好:[籃球, 足球, 編程]

從字符串解析的 User:
用戶ID:1002
姓名:李四
地址:浙江省-杭州市
愛好:[讀書, 旅行]

四、復(fù)雜場景擴(kuò)展

1. 集合根節(jié)點(diǎn)(多個(gè)對(duì)象的 XML 序列化)

若需序列化多個(gè) User 對(duì)象(如 List<User>),直接序列化集合會(huì)報(bào)錯(cuò)(無根元素),需創(chuàng)建一個(gè)“包裝類”:

@XmlRootElement(name = "users")
@XmlAccessorType(XmlAccessType.FIELD)
public class UserList {
    @XmlElement(name = "user") // 每個(gè) User 對(duì)應(yīng) <user> 子元素
    private List<User> userList;

    public UserList() {}
    public UserList(List<User> userList) {
        this.userList = userList;
    }

    // getter/setter
}

序列化示例:

List<User> users = Arrays.asList(user1, user2);
UserList userList = new UserList(users);
marshaller.marshal(userList, new File("users.xml"));

生成的 XML:

<users>
    <user id="1001">...</user>
    <user id="1002">...</user>
</users>

2. 日期格式自定義

默認(rèn)日期字段(Date/LocalDate)序列化格式不友好,可通過 @XmlJavaTypeAdapter 自定義適配器:

步驟 1:實(shí)現(xiàn)日期適配器

import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.text.SimpleDateFormat;
import java.util.Date;

// 適配 Date <-> String(自定義格式)
public class DateAdapter extends XmlAdapter<String, Date> {
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public Date unmarshal(String xmlStr) throws Exception {
        return sdf.parse(xmlStr);
    }

    @Override
    public String marshal(Date date) throws Exception {
        return sdf.format(date);
    }
}

步驟 2:在實(shí)體類字段上使用

@XmlElement(name = "createTime")
@XmlJavaTypeAdapter(DateAdapter.class) // 應(yīng)用適配器
private Date createTime;

序列化后 XML 效果:

<createTime>2025-11-25 14:30:00</createTime>

3. 忽略空值字段

默認(rèn)情況下,空值字段(如 age = null)會(huì)生成空的 XML 元素(<age/>),可通過配置 Marshaller 忽略空值:

// JAXB 2.2+ 支持,需引入 jaxb-impl 依賴
marshaller.setProperty("com.sun.xml.bind.marshaller.NullPolicy", NullPolicy.SKIP);

或通過注解 @XmlElement(nillable = false) 配合配置:

@XmlElement(nillable = false)
private Integer age;

五、常見問題與注意事項(xiàng)

1. 報(bào)錯(cuò)JAXBException: Class ... nor any of its super class is known to this context

  • 原因:JAXBContext.newInstance(...) 未傳入所有參與序列化的類(如嵌套類、集合元素類)。
  • 解決:確保所有相關(guān)類都被包含,如 JAXBContext.newInstance(User.class, Address.class)。

2. 報(bào)錯(cuò)No default constructor found

  • 原因:實(shí)體類(或嵌套類)沒有默認(rèn)無參構(gòu)造器。
  • 解決:為所有實(shí)體類添加無參構(gòu)造器(即使是空實(shí)現(xiàn))。

3. 中文亂碼

  • 原因:Marshaller 編碼未設(shè)置為 UTF-8,或文件讀取時(shí)編碼不匹配。
  • 解決:
    marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); // 序列化時(shí)
    // 反序列化文件時(shí)指定編碼
    FileInputStream fis = new FileInputStream(xmlFile);
    User user = (User) unmarshaller.unmarshal(new InputStreamReader(fis, "UTF-8"));
    

4. JDK 9+ 模塊訪問限制

  • 報(bào)錯(cuò):Module java.base does not "opens java.lang" to unnamed module @xxx
  • 解決:運(yùn)行時(shí)添加 JVM 參數(shù),開放模塊訪問:
    --add-opens java.base/java.lang=ALL-UNNAMED
    --add-opens java.base/java.util=ALL-UNNAMED
    

六、核心 API 總結(jié)

類/接口作用核心方法
JAXBContext管理綁定關(guān)系(線程安全,可復(fù)用)newInstance(Class...):創(chuàng)建上下文
MarshallerJava 對(duì)象 → XMLmarshal(Object, OutputStream/File/StringWriter)
UnmarshallerXML → Java 對(duì)象unmarshal(InputStream/File/StringReader)

通過以上步驟,你可以完整實(shí)現(xiàn) XML 與 Java 對(duì)象的相互轉(zhuǎn)換,覆蓋基本場景和常見復(fù)雜需求。JAXB 無需手動(dòng)解析 XML 標(biāo)簽,通過注解自動(dòng)映射,大幅簡化 XML 處理代碼。

到此這篇關(guān)于javax.xml.bind.JAXBContext操作XML的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)javax.xml.bind.JAXBContext操作XML內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

宁蒗| 林口县| 方城县| 寻甸| 民县| 大安市| 三门峡市| 勃利县| 成安县| 岢岚县| 信阳市| 临沂市| 辰溪县| 沐川县| 阿坝县| 郓城县| 五华县| 徐闻县| 高青县| 西平县| 南通市| 江永县| 刚察县| 安泽县| 海晏县| 夏邑县| 台北市| 和硕县| 元谋县| 张家界市| 章丘市| 英山县| 垫江县| 东宁县| 祁东县| 行唐县| 南漳县| 葵青区| 电白县| 高陵县| 肃北|