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

Spring MVC 返回 XML 實戰:JAXB 註解驅動、統一響應包裝、泛型數據支持

     編輯:Java 綜合教學

Spring MVC 返回 XML 實戰:JAXB 註解驅動、統一響應包裝、泛型數據支持

雖然 JSON 為主流,但金融、政企、對接舊系統等場景仍強制要求 **XML 響應**。Spring MVC 內置 `Jaxb2RootElementHttpMessageConverter`,**零額外依賴** (JDK 6+ 內置 JAXB) 即可實現對象自動轉 XML。本文演示**實體類 JAXB 註解、統一響應基類、泛型數據字段、Controller 返回、XML 輸出效果**全流程。

一、Maven 依賴 (Spring MVC 基礎)

<dependencies>
    <dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.25</version></dependency>
    <!-- JAXB 在 JDK 6-10 內置;JDK 11+ 需額外引入 -->
    <dependency>
        <groupId>jakarta.xml.bind</groupId>
        <artifactId>jakarta.xml.bind-api</artifactId><version>2.3.3</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId><version>2.3.3</version>
    </dependency>
</dependencies>

二、統一響應基類:BaseXmlResult

public class BaseXmlResult {
    protected String code;    // 業務狀態碼:0000 成功、其它失敗
    protected String message; // 提示信息

    public String getCode() { return code; }
    public void setCode(String code) { this.code = code; }
    public String getMessage() { return message; }
    public void setMessage(String message) { this.message = message; }
}

三、泛型數據響應類:XmlActionResult<T>

@XmlRootElement(name = "xml")           // XML 根元素名 
@XmlAccessorType(XmlAccessType.NONE)    // 僅序列化標註字段
public class XmlActionResult<T> extends BaseXmlResult {
    @XmlElements({                       // 多態支持:根據實際類型輸出對應標籤
        @XmlElement(name = "Person", type = Person.class),
        @XmlElement(name = "Man", type = Man.class),
        @XmlElement(name = "Woman", type = Woman.class)
    })
    private T data;                      // 泛型業務數據

    public T getData() { return data; }
    public void setData(T data) { this.data = data; }
    // 繼承 code、message getter/setter
}

關鍵點:

  • `@XmlRootElement(name="xml")`:指定根標籤 ``
  • `@XmlAccessorType(XmlAccessType.NONE)`:字段默認不序列化,**必須在字段/方法上顯式加 `@XmlElement`**
  • `@XmlElements`:解決泛型擦除導致無法確定具體類型,運行時根據實際對象類型輸出對應標籤名

四、實體類:Person / Man / Woman

@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class Person {
    @XmlElement private String name;
    @XmlElement private Integer sex;   // 1 男 2 女
    @XmlElement private Integer age;
    private Date birthday;             // 無 @XmlElement → 不輸出

    public Person() {}
    public Person(String name, Integer sex, Integer age) {
        this.name = name; this.sex = sex; this.age = age;
    }
    // getter/setter 省略
    // birthday 僅作演示:若需輸出需加 @XmlElement + @XmlJavaTypeAdapter 格式化日期
}

public class Man extends Person {
    public Man(String name, int age) { super(name, 1, age); }
}
public class Woman extends Person {
    public Woman(String name, int age) { super(name, 2, age); }
}

五、Controller 實現

@Controller
@RequestMapping("/mvc")
public class HelloController {
    @GetMapping("/helloXmlPerson/{name}")
    @ResponseBody  // 關鍵:觸發 HttpMessageConverter 轉換
    public XmlActionResult<Person> helloXmlPerson(@PathVariable String name) {
        XmlActionResult<Person> result = new XmlActionResult<>();
        result.setCode("0000");
        result.setMessage("請求成功: " + name);
        result.setData(new Person("張三", 1, 28));
        return result;
    }
}

六、Spring MVC 配置啟用

<mvc:annotation-driven /> <!-- 自動註冊 Jaxb2RootElementHttpMessageConverter -->
或 JavaConfig:
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new Jaxb2RootElementHttpMessageConverter());
    }
}

七、實際 XML 輸出效果

GET /mvc/helloXmlPerson/nihao

<xml>
    <code>0000</code>
    <message>請求成功: nihao</message>
    <Person>
        <name>張三</name>
        <sex>1</sex>
        <age>28</age>
    </Person>
</xml>

若 `setData(new Woman("李四", 25))`,輸出 `...`,實現**多態 XML 輸出**。

八、進階:日期格式化、命名空間、CDATA

需求解決方案
日期格式化字段加 `@XmlJavaTypeAdapter(DateAdapter.class)`,實現 `XmlAdapter` 的 `marshal/unmarshal`
XML 命名空間包級註解 `@XmlSchema(namespace="https://example.com", elementFormDefault=XmlNsForm.QUALIFIED)` (package-info.java)
CDATA 區塊字段類型用 `javax.xml.bind.annotation.XmlCDATA` 包裝類,或自定義 Adapter 輸出 ``
集合輸出包裝標籤`@XmlElementWrapper(name="persons")` + `@XmlElement(name="person")` → `...`

九、常見坑與避雷

  1. JDK 11+ 移除 JAXB:必須額外引入 `jakarta.xml.bind-api` + `jaxb-runtime`,且包名從 `javax.xml.bind` 變為 `jakarta.xml.bind`。
  2. 字段未加 @XmlElement:配合 `XmlAccessType.NONE` 會導致字段不輸出;或改用 `FIELD`/`PROPERTY` 訪問類型。
  3. 泛型擦除導致標籤名固定:必須用 `@XmlElements` 列出所有可能實現類,或自定義 `Jaxb2RootElementHttpMessageConverter` 覆寫 `getJavaType`。
  4. Boolean 輸出 true/false 小寫:JAXB 默認小寫,符合 XML Schema 標準,無需修改。
  5. 大數據量 XML 性能:JAXB 樹模型佔用內存大,流式場景考慮 StAX (`XMLStreamWriter`) 手寫輸出。

十、總結

Spring MVC 返回 XML **零配置、零額外依賴 (JDK 內置 JAXB)**,核心在於:**實體類標註 JAXB 註解、統一響應基類封裝 code/message、泛型數據用 `@XmlElements` 支持多態、Controller 加 `@ResponseBody`、啟用 ``**。掌握此套方案,可優雅應對「必須返回 XML」的強制需求,同時保持代碼結構清晰、擴展性強。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved