Java 对象到 xml 模式自定义映射 - Web 服务

标签 java xml jaxb marshalling

我在 JAX-WS 中有一个 Web 服务,pom.xml 中的 maven goal('ws-jwsc') 生成 WSDL 文件以及输入和输出 XSD。

我想以不同的方式更改 java 类属性到 WSDL/XSD 架构的映射,如下所示:

我有两个类(class) 1) 客户 2) 位置

<强>1。客户 - 客户特定信息

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

   public Customer() {
      super();
   }

   public Customer(CustomerType customerType) {
      this.customerType = customerType;
   }

   public enum CustomerType {
      B, S, C
   }

   private CustomerType customerType;

   private String name;

   private Long accountNumber;

   private Location location;

   // getter/setter for properties

}

<强>2。 Location - 包含 addr1/addr2/city/state/zip/country 的位置对象

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Location {

   private String address1;

   private String address2;

   private String city;

   private String state;

   private String zip;

   private String country;

   /**
    * @return the city
    */`enter code here`
   public String getCity() {
      return city;
   }

 //getter/setter for properties

}

现在我的问题是在运行时可以有 3 个值 ('B','C','S') Customer 类中的“customerType”属性

所以,
例如,如果 customerType 的运行时值为“S”。

然后代码应生成 Location 对象属性为 'ShipperAddress1', 'ShipperAddress2', 'ShipperCity', 'ShipperState', 'ShipperZip', 'ShipperCountry' for 'address1' , 'address2', 'city', 'state', 'zip' and 'country'分别在 SOAP 响应 XML 中包含属性。

示例2:如果 customerType 的运行时值为“C”。

然后代码应生成 Location 对象属性为 'ConsigneeAddress1', 'ConsigneeAddress2', 'ConsigneeCity', 'ConsigneeState', 'ConsigneeZip', 'ConsigneeCountry' for 'address1' , 'address2', 'city', 'state', 'zip' and 'country'分别在 SOAP 响应 XML 中包含属性。

我需要知道是否可以这样做,如果可以,那么如何? 非常感谢所有的帮助。

最佳答案

您可以很好地做到这一点,使用@XmlElementRef,然后使用“位置继承”。

拥有 LocationAbstractLocation 的基类,然后为客户类型托运人或收货人“创建”Location 实例,并覆盖子类中的元素名称。我在下面有一个示例来演示我在一个字段 Address1 中显示它的位置。您可以类似地覆盖所有必填字段。

请注意,我没有使用Field访问类型,而是将其设为Property,以便我们仅覆盖方法,并且字段仍保持“私有(private)” > 在基类中。如果您认为字段可以受到保护,您也可以进行调整。

示例

在示例中,我刚刚使用了 LocationC 和 LocationS。您可以添加 LocationB

Customer.java with main class. Note @XmlElementRef(name = "Location")

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

    public CustomerType getCustomerType() {
        return customerType;
    }

    public void setCustomerType(CustomerType customerType) {
        this.customerType = customerType;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getAccountNumber() {
        return accountNumber;
    }

    public void setAccountNumber(Long accountNumber) {
        this.accountNumber = accountNumber;
    }

    public GeneralLocation getLocation() {
        return location;
    }

    public void setLocation(GeneralLocation location) {
        this.location = location;
    }

    public Customer() {
        super();
    }

    public Customer(CustomerType customerType) {
        this.customerType = customerType;
    }

    public enum CustomerType {
        B, S, C
    }

    private CustomerType customerType;

    private String name;

    private Long accountNumber;

    @XmlElementRef(name = "Location")
    private GeneralLocation location;

    public static void main(String[] args) throws Exception {
        Customer c = new Customer();
        c.setAccountNumber(1111111l);
        c.setCustomerType(CustomerType.C);
        LocationC loc = new LocationC();
        loc.setAddress1("I am address 1");
        c.setLocation(loc);

        Customer c2 = new Customer();
        c2.setAccountNumber(222222l);
        c.setCustomerType(CustomerType.S);
        LocationS locs = new LocationS();
        locs.setAddress1("I am S address 1");
        c2.setLocation(locs);
        JAXBContext jc = JAXBContext.newInstance(Customer.class);
        Marshaller marrshaller = jc.createMarshaller();
        marrshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

        marrshaller.marshal(c, System.out);
        marrshaller.marshal(c2, System.out);
    }

}

Base AbstractLocation.java (I have hidden it's property using annotation @XmlTransient.

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlTransient;


@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlSeeAlso({LocationC.class, LocationS.class})
abstract class GeneralLocation {

   private String address1;

   private String address2;

   private String city;

   private String state;

   private String zip;

   private String country;

   @XmlTransient()
    public String getAddress1() {
        return address1;
    }

    public void setAddress1(String address1) {
        this.address1 = address1;
    }

    public String getAddress2() {
        return address2;
    }

    public void setAddress2(String address2) {
        this.address2 = address2;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getZip() {
        return zip;
    }

    public void setZip(String zip) {
        this.zip = zip;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }
}

LocationC.java

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement()
public class LocationC extends GeneralLocation {

    @XmlElement(name="ConsigneeAddress1")
    @Override
    public String getAddress1() {
        return super.getAddress1();
    }
}

LocationS.java

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement()
@XmlAccessorType(XmlAccessType.PROPERTY)
public class LocationS  extends GeneralLocation {

    @XmlElement(name="ShipperAddress1")
    public String getAddress1() {
        return super.getAddress1();
    }
}

关于Java 对象到 xml 模式自定义映射 - Web 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47062928/

相关文章:

java - 我可以查看该程序的另一个示例吗?我很难理解它

java - 声明 sigmoid 函数时出现的问题

java - 在 JPanel 中获得良好的网格布局

java - 某些 mipmap 不显示

java - 使用 Java 解码来自 Bing Translate 的 REST 响应

java - Groovy 脚本编译为类

sql - 如何在 SQL Server 2008 R2 中根据参数名称检索 xml 数据类型中的属性值?

java - Doclava - 如何生成版本控制的 xml?

java - 具有自定义拦截器的 JAXB 解码器?

java - JAXB-2 Maven 插件、模式包含和绑定(bind)