java - 如何使用XML/XSD定义JAXB抽象类并实现继承?

标签 java xml jaxb xsd jms

寻找一种方法来定义一个基本 XML 模式,以便在其他模式上重新使用,作为将用于不同 JMS 消息有效负载的 XML 消息。目的是:

  • XmlMessage - 定义一个基本消息类,所有消息都将作为该类发送。
  • header - 所有消息都将包含的类,其中包含有关消息的元数据
  • 主体 - 每个特定消息实现可用于定义每个单独消息的消息负载的抽象类

这种方法将:

  • 允许 JMS EJB 将传入的 XML 解码为高级通用 XmlMessage,然后能够评估 Body 实现的类类型以确定如何处理消息。
  • 标准化各种消息格式。
  • 利用 JAXB 生成要在发送消息的客户端和处理消息的 EJB 上使用的 Java 类。
  • 利用 JAXB 编码/解码消息负载中的 XML。

最佳答案

请参阅以下 XSD 模式和 JAXB 实现来完成为消息正文定义抽象类

XmlMessage.xsd 定义所有消息的格式:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.samnunnally.com" targetNamespace="http://www.samnunnally.com" version="1.0">
<xs:element name="xmlMessage">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="header" type="header" minOccurs="1" maxOccurs="1"/>
            <xs:element ref="body"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>
<xs:complexType name="header">
    <xs:sequence>
        <xs:element name="message_class" type="xs:string"/>
        <xs:element name="message_id" type="xs:int"/>
        <xs:element name="message_length" type="xs:int"/>
        <xs:element name="software_version" type="xs:string"/>
        <xs:element name="correlation_id" type="xs:string"/>
        <xs:element name="session_id" type="xs:string"/>
        <xs:element name="return_code" type="xs:string"/>
    </xs:sequence>
</xs:complexType>
<xs:element name="body" type="body"/>
<xs:complexType name="body" abstract="true">
    <xs:sequence/>
</xs:complexType>

实现 XmlMessage.xsd 的示例 xsd。最终成为包含客户列表的消息 Foo。关键是使用 substitutionGroup 属性和 xs:extension base="body"

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
       xmlns="http://www.samnunnally.com" 
       targetNamespace="http://www.samnunnally.com" 
       version="1.0">
<xs:include schemaLocation="XmlMessage.xsd"/>
<xs:element name="foo" type="foo" substitutionGroup="body"/>
<xs:complexType name="foo">
    <xs:complexContent>
        <xs:extension base="body">
            <xs:sequence>
                <xs:element name="customers" type="customer" minOccurs="1" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>
<xs:complexType name="customer">
    <xs:sequence>
        <xs:element name="customer_id" type="customerId" nillable="false" minOccurs="1" maxOccurs="1"/>
        <xs:element name="name" type="xs:string"/>
        <xs:element name="street" type="xs:string"/>
        <xs:element name="city" type="xs:string"/>
        <xs:element name="state" type="xs:string"/>
        <xs:element name="zip" type="xs:string"/>
        <xs:element name="phone" type="xs:string"/>
    </xs:sequence>
</xs:complexType>
<xs:complexType name="customerId">
    <xs:sequence>
        <xs:element name="id" type="xs:string" minOccurs="1" maxOccurs="1"/>
    </xs:sequence>
</xs:complexType>

JAXB 生成的关键 Java 类:

留言:

package com.samnunnally;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "header",
    "body"
})
@XmlRootElement(name = "xmlMessage")
public class XmlMessage {

    @XmlElement(required = true)
    protected Header header;
    @XmlElementRef(name = "body", namespace = "http://www.samnunnally.com", type = JAXBElement.class)
    protected JAXBElement<? extends Body> body;

    public Header getHeader() {
        return header;
    }

    public void setHeader(Header value) {
        this.header = value;
    }

    public JAXBElement<? extends Body> getBody() {
        return body;
    }

    public void setBody(JAXBElement<? extends Body> value) {
        this.body = value;
    }
}

正文:

package com.samnunnally;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "body")
@XmlSeeAlso({
Foo.class
})
public abstract class Body {
}

Foo 消息:

package com.samnunnally;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "foo", propOrder = {
    "customers"
})
public class Foo
    extends Body
{

    @XmlElement(required = true)
    protected List<Customer> customers;

    public List<Customer> getCustomers() {
        if (customers == null) {
            customers = new ArrayList<Customer>();
        }
        return this.customers;
    }

}

关于java - 如何使用XML/XSD定义JAXB抽象类并实现继承?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20169251/

相关文章:

java - 如何将字符串放置在二维数组中随机选择的位置

Java:通过正则表达式字符串解析用元素丰富 xml

java - 生成的 XML 中存在意外属性

java - 使用 DTD 文件导致的 JAXB 解码 XML 时出错

并行部分任务的 Java 并发模式

java - core-nlp 共指解析 : remaping co-references

java - Android:滚动包含recyclerView的 subview 时如何滚动parentView

java - XSD 架构元素可以是两种类型之一

java - 如何使用 Maven 插件在构建路径中添加多个生成的文件夹

java - Visual Studio Java IDE