WebService对象可空的困惑,关于nillable和minOccurs

本文详细探讨了WebService中minOccurs和nillable属性的定义及其在值类型、包装类型和普通引用类型中的不同规则。通过Java和.NET平台的实例分析,揭示了两者在生成WSDL时的规则差异,以及由WSDL生成代码时的处理方式。作者指出,Java在处理null对象时更为简洁,而.NET的处理方式可能导致一些不必要的复杂性,如生成的xxxSpecified属性。文章最后总结了在设计自己的WSDL生成框架时应遵循的原则。
摘要由CSDN通过智能技术生成

术语约定
文章中会反复出现[值类型]、[包装类型]、[普通引用类型]、[元素节点]和[元素取值]的表述
1> [值类型]指的是java和.NET中的基本数据类型,如:int;
2> [包装类型]指的是java中的包装类和.NET中的Nullable<T>类型,如:Integer、int?;
3> [普通引用类型]指的是除包装类型外的其它引用类型;
4> [元素节点]指的是xml文档中的一个标签节点,我们可以说[元素节点]是必输还是非必输,如:<Name>lubiao</Name>;
5> [元素取值]指的是xml标签节点的内容,我们可以说[元素取值]是空还是非空,如:<Name>lubiao</Name>表示元素取值不为空,<Name xsi:nil="true"/>表示元素取值为空;

1、首先来看minOccurs和Nillable的定义
minOccurs
:表示XML文档中某个[元素节点] 是否可以不出现,默认值为1,表示必须出现
nillable:表示XML文档中某个[元素取值] 是否可以为空(形如:<name xsi:nil="true" />),默认值为false,表示不能为空
那么,minOccurs和nillable的组合形式就会有4种,如下:
例一,值类型:

<element name="id1" type="int" minOccurs="0" nillable="true"/>
<element name="id2" type="int" minOccurs="0" nillable="false"/>
<element name="id3" type="int" minOccurs="1" nillable="true"/>
<element name="id4" type="int" minOccurs="1" nillable="false"/>

例二,引用类型:

<element name="name1" type="string" minOccurs="0" nillable="true"/>
<element name="name2" type="string" minOccurs="0" nillable="false"/>
<element name="name3" type="string" minOccurs="1" nillable="true"/>
<element name="name4" type="string" minOccurs="1" nillable="false"/>

2、Java和.NET自动生成WSDL的规则
在实际开发时我们通常的做法是先编写Server端代码,然后利用工具自动生成wsdl描述,最后再利用工具读取wsdl进而生成客户端程序。那么用工具生成wsdl和用工具反向生成代理程序的规则是什么呢?下来对此进行实例分析:
2.1 先看.NET生成wsdl的规则
实验时所用的开发工具为VS 2010,用vs开发WebService的资料,百度搜索一大推,这里不赘述。
2.1.1、定义数据实体:Person.cs

public class Person 
{
    public int Id { get; set; } //值类型
    public string Name { get; set; }//普通引用类型
    public int? PhoneNbr { get; set; }//包装类型
}

2.1.2、定义服务类:WebService.cs

/// <summary>
///WebService 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService {

    public WebService () {
       //如果使用设计的组件,请取消注释以下行 
        //InitializeComponent(); 
    }

    [WebMethod]
    public string HelloWorld(int id,int? phoneNbr,string name,Person person) {
        return "Hello World";
    }
    
}

helloWorld方法有4个参数,前三个参数和Person类的三个属性是一样的,加入这三个参数的目的是进行对比测试。
2.1.3、查看生成的wsdl

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    <s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
      <s:element name="HelloWorld">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="1" maxOccurs="1" name="id" type="s:int" />
            <!--nillable默认为false,minOccurs等于1:即id元素为必输,且值不能为空-->
            <s:element minOccurs="1" maxOccurs="1" name="phoneNbr" nillable="true" type="s:int" />
            <!--nillable等于true,minOccurs等于1:即phoneNbr元素为必输,但值可以为空-->
            <s:element minOccurs="0" maxOccurs="1" name="name" type="s:string" />
            <!--nillable默认为false,minOccurs等于0:即name元素为非必输,但值不能为空-->
            <s:element minOccurs="0" maxOccurs="1" name="person" type="tns:Person" />
            <!--nillable默认为false,minOccurs等于0:即person元素为非必输,但值不能为空-->
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:complexType name="Person">
        <s:sequence>
          <s:element minOccurs="1" maxOccurs="1" name="Id" type="s:int" />
          <!--nillable默认为false,minOccurs默认为1:即id元素为必输,且值不能为空-->
          <s:element minOccurs="0" maxOccurs="1" name="Name" type="s:string" />
          <!--nillable默认为false,minOccurs等于0:即Name元素为非必输,但值不能为空-->
          <s:element minOccurs="1" maxOccurs="1" name="PhoneNbr" nillable="true" type="s:int" />
          <!--nillable默认为false,minOccurs等于1:即PhoneNbr元素为必输,但值可以为空-->
        </s:sequence>
      </s:complexType>
      <s:element name="HelloWorldResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="HelloWorldResult" type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
    </s:schema>
  </wsdl:types>
 </wsdl:definitions>

2.1.4、得出结论  
*
id参数和Person.Id属性都为值类型:[元素节点] 都必输,[元素取值] 都不能为空
* phoneNbr参数和Person.PhoneNbr属性都是包装类型:[元素节点] 都必输,但[元素取值] 都可以为空;
* name参数和Person.Name属性都是普通引用类型:[元素节点] 都可以不输,但[元素取值] 都不能为空;
* person参数是普通引用类型:[元素节点] 可以不输,但[元素取值] 不能为空。
2.2 再看Java的规则
首先,先熟悉在eclipse中快速开发webservice程序的步骤,参考链接:http://www.blogjava.net/parable-myth/archive/2010/08/03/327802.html,此次实验采用的就是这种快速开发方式(注:不同的框架和工具会可能会有不同的生成规则),所用ecllipse版本为:
    Version: Juno Service Release 1
    Build id: 20121004-1855
2.2.1、定义数据实体:Person.java

package com.lubiao.axis;

public class Person  implements java.io.Serializable {
    private int id;//编号,值类型
    private java.lang.String name;//姓名,普通引用类型
    private Integer phoneNbr;//电话,包装类型
    
    public int getId() {return id;}
    public void setId(int id) {this.id = id;}
	
    public java.lang.String getName() {return name;}
    public void setName(java.lang.String name) {this.name = name;}

    public Integer getPhoneNbr() {return phoneNbr;}
    public void setPhoneNbr(Integer phoneNbr) {this.phoneNbr = phoneNbr;}
}

2.2.2、定义服务类:WebServiceTest.java

package com.lubiao.axis;

public class WebServiceTest{
	public String helloWorld(int id,Integer phoneNbr,String name,Person person){
		return "Hello World";
	}
}

helloWorld方法有4个参数,前三个参数和Person类的三个属性是一样的,加入这三个参数的目的是进行对比测试。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值