minOccurs,nillable和限制的目的是什么?

所需文件说:

如果required()true ,则Javabean属性将映射到具有minOccurs="1"的XML模式元素声明。 对于单值属性, maxOccurs"1" ,对于多值属性, maxOccurs"1" "unbounded"

如果required()false ,则Javabean属性将映射到XML Schema元素声明,其中minOccurs="0" 。 对于单值属性, maxOccurs"1" ,对于多值属性, maxOccurs"1" "unbounded"

nillable的文档说:

如果nillable()true ,则JavaBean属性将映射到XML Schema nillable元素声明。


xs:complexType代码xs:complexType

 public class WSData { //... @XmlElement(required = true, nillable = false) public void setMonth(XmlMonthType month) { this.month = month; } public void setUserLogin(String userLogin) { this.userLogin = userLogin; } } 

xs:simpleType代码xs:simpleType

 @XmlType @XmlEnum(Integer.class) public enum XmlMonthType { @XmlEnumValue("1") JANUARY, @XmlEnumValue("2") FEBRUARY, @XmlEnumValue("3") MARCH, /* ... months 4 ~9 ... */ @XmlEnumValue("10") OCTOBER, @XmlEnumValue("11") NOVEMBER, @XmlEnumValue("12") DECEMBER; } 

生成的XML架构:

                  

事实:

  1. minOccurs的默认值是1.因此, 月份是必需的(必须存在);
  2. 这个月有限制 。 因此, month只能有一个由12个定义的枚举之一定义的值;
  3. nillable的默认值为false。 所以, 月份不能有空值;
  4. XML Schema正确生成。

问题:

  1. 它接受月份的贬值(必须不存在);
  2. 它接受月份的任何值,如13(除非不能解析为Integer);
  3. 它接受空值;

我没想到会遇到这些问题,我错过了什么吗?
如果这种行为是正确的,那么requirednillablexs:restriction的目的是什么?

Nillable允许空值。 例如,如果您有一个Integer或Date,如果它是可为空的,则XML标记可能为空。 如果它不是可存档但不是必需的,那么XML元素要么必须存在有效​​内容,要么根本不存在; 空标签无效。

使minOccurs 1,需要月份;

minOccurs的默认值为1,因此month元素是必需的。 注意如何将minOccurs="0"添加到userLogin以使其成为可选项。

       

使用生成的限制validation月份(不使用XmlAdapter)。

您可以在Unmarshaller上设置Schema实例以validation输入:

演示

以下代码可用于生成XML架构:

 package forum9111936; import java.io.IOException; import javax.xml.bind.JAXBContext; import javax.xml.bind.SchemaOutputResolver; import javax.xml.transform.Result; import javax.xml.transform.stream.StreamResult; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(WSData.class); SchemaOutputResolver sor = new SchemaOutputResolver() { @Override public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException { StreamResult result = new StreamResult(System.out); result.setSystemId(suggestedFileName); return result; } }; jc.generateSchema(sor); System.out.println(); } } 

UPDATE

JAXB RI通常会针对转换问题抛出严重性为1的ValidationEvent 。 默认的ValidationEventHandler忽略严重性小于2的所有问题。这通常会导致将值设置为null。 您可以按如下方式覆盖ValidationEventHandler

  unmarshaller.setEventHandler(new ValidationEventHandler() { @Override public boolean handleEvent(ValidationEvent event) { System.out.println(event); return event.getSeverity() < ValidationEvent.ERROR; } }); 

但是,JAXB RI似乎不会抛出与转换枚举值相关的事件(可能的错误)。 如果您恰好使用EclipseLink JAXB(MOXy)作为JAXB提供程序,那么您将获得如下exception:

 Exception in thread "main" Local Exception Stack: Exception [EclipseLink-116] (Eclipse Persistence Services - 2.4.0.qualifier): org.eclipse.persistence.exceptions.DescriptorException Exception Description: No conversion value provided for the value [13] in field [month/text()]. Mapping: org.eclipse.persistence.oxm.mappings.XMLDirectMapping[month-->month/text()] Descriptor: XMLDescriptor(forum9111936.WSData --> []) at org.eclipse.persistence.exceptions.DescriptorException.noFieldValueConversionToAttributeValueProvided(DescriptorException.java:1052) at org.eclipse.persistence.mappings.converters.ObjectTypeConverter.convertDataValueToObjectValue(ObjectTypeConverter.java:140) at org.eclipse.persistence.oxm.mappings.XMLDirectMapping.getAttributeValue(XMLDirectMapping.java:287) at org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue.endElement(XMLDirectMappingNodeValue.java:190) at org.eclipse.persistence.oxm.record.UnmarshalRecord.endElement(UnmarshalRecord.java:910) at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parseEvent(XMLStreamReaderReader.java:133) at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parse(XMLStreamReaderReader.java:83) at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parse(XMLStreamReaderReader.java:72) at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:838) at org.eclipse.persistence.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:626) at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:472) at forum9111936.Demo2.main(Demo2.java:30) 

了解更多信息

requiredminOccurs的目的不是误导,问题是未启用模式validation。 只需将SchemaValidation 启用WebService定义 XmlType映射的顺序 ,如下所示:

网络服务:

 @javax.jws.WebService @org.jboss.ws.annotation.SchemaValidation(enabled = true) public class WebServiceClass { @javax.jws.WebMethod public WSResponseData webServiceMethod() { //... } } 

XmlType将:

 @javax.xml.bind.annotation.XmlType(propOrder = {"field1", "field2", "field3"}) public class WSData { //... private String field1; private Long field2; private XmlMonthType field3; //... } 

实际上,似乎SOAP信封在WSDL上未经过validation,无论是在服务器上还是在客户端上。

而且我认为这种方式最好。 validation会消耗资源和时间。 对于大多数WebServices,我们需要的所有WSDL都是向客户端提供能够与WebService通信的定义,而不是设置限制,例如属性是否可以为null。

当服务器和客户端在同一台PC上时,与内部呼叫相比,Axis2增加了3-5百万的开销。 不必要的validation只会增加开销。 我最好让操作抛出exception并手动validation真正需要的东西。

我查看了你发布的XSD结构 – 并发现你没有使用你在本月定义的复杂类型,在java代码中处理它的Insteqad你可以在XSD中提及所有这些,以及月份的minOccur – 复杂类型中的元素缺失。 请使用任何standered XSD到java生成器,它将为您完成所有java文件生成任务

 The convention are as follow - MinOccur = 0 --> the element can be abscent in input , and can be present MinOccur = 1 --> the element must be there in input (but if you use it, then your java generated member will be of list type - list of ENUM for Int ) If you don't write MinOccur in attributes - then it makes the element mandatory , ( then you java generated member will be of simply ENUM for int ) MaxOccur = 1 --> minimum one element can be there in input (but if you use it, then your java generated member will be of list type - list of ENUM for Int ) MaxOccur = unbound --> only one element can be there in input (if you use it, then your java generated member will be of list type - list of ENUM for Int )