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 Schemanillable
元素声明。
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架构:
事实:
- minOccurs的默认值是1.因此, 月份是必需的(必须存在);
- 这个月有限制 。 因此, month只能有一个由12个定义的枚举之一定义的值;
- nillable的默认值为false。 所以, 月份不能有空值;
- XML Schema正确生成。
问题:
- 它接受月份的贬值(必须不存在);
- 它接受月份的任何值,如13(除非不能解析为Integer);
- 它接受空值;
我没想到会遇到这些问题,我错过了什么吗?
如果这种行为是正确的,那么required , nillable和xs: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)
了解更多信息
required
和minOccurs
的目的不是误导,问题是未启用模式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 )