Skip to content

Instantly share code, notes, and snippets.

@ufologist
Created September 8, 2012 15:20
Show Gist options
  • Save ufologist/3675931 to your computer and use it in GitHub Desktop.
Save ufologist/3675931 to your computer and use it in GitHub Desktop.
怎样通过ksoap2发送复杂参数给web service方法(How to send complex type using ksoap2)
/*
* copyright
*/
package com.ufologist.model;
/**
* 公用模型
*
* @author Sun
* @version 1.0 2012-9-8
*/
public class Foo {
/**
* 必须使用int类型, 因为当不设置此属性时, KSOAP2会得到默认值0.
*
* 如果是Integer类型, 未设置属性的情况下, KSOAP2只会得到null, 此时会报错
* SoapFault - faultcode: 'soap:Server' faultstring: 'Illegal argument. For input string: ""' faultactor: 'null' detail: null
*/
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/*
* copyright
*/
package com.ufologist.model.stub;
import java.util.Hashtable;
import org.ksoap2.serialization.KvmSerializable;
import org.ksoap2.serialization.PropertyInfo;
import com.ufologist.model.Foo;
/**
* KSOAP2模型序列化实现类
*
* @author Sun
* @version 1.0 2012-9-8
*/
public class Foo_ extends Foo implements KvmSerializable {
/**
* 自定义类型(对象)所处的命名空间.
* 从wsdl(xsd:schema节点targetNamespace属性)中可以找到
*
* 例如:
* <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified"
* targetNamespace="http://model.ufologist.com">
* <xsd:complexType name="Foo">
* <xsd:sequence>
* <xsd:element minOccurs="0" name="id" type="xsd:int"/>
* <xsd:element minOccurs="0" name="name" nillable="true" type="xsd:string"/>
* </xsd:sequence>
* </xsd:complexType>
* </xsd:schema>
*/
public static final String NAMESPACE = "http://model.ufologist.com";
@Override
public Object getProperty(int index) {
Object value = null;
switch (index) {
case 0:
value = getId();
break;
case 1:
value = getName();
break;
}
return value;
}
@Override
public int getPropertyCount() {
return 2;
}
@Override
public void getPropertyInfo(int index, Hashtable properties,
PropertyInfo info) {
switch (index) {
case 0:
info.name = "id";
info.type = PropertyInfo.INTEGER_CLASS;
// 必须设置对象属性所处的命名空间.
// KSOAP2将对象序列化成SOAP XML时才会在对应的命名空间下.
// 生成的XML类似:
// <n0:foo i:type="n0:Foo" xmlns:n0="http://model.ufologist.com">
// <n0:id i:type="d:int">0</n0:id>
// </n0:foo>
//
// 如果没有设置命名空间, 生成的XML类似(foo处于默认命名空间下明显不对):
// <foo i:type="n0:Foo" xmlns:n0="http://model.ufologist.com">
// <id i:type="d:int">0</id>
// </foo>
// 通过KSOAP2调用WebService会返回错误信息
// <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
// <soap:Body>
// <soap:Fault>
// <faultcode>soap:Server</faultcode>
// <faultstring>Fault: java.lang.NullPointerException</faultstring>
// </soap:Fault>
// </soap:Body>
// </soap:Envelope>
// 抛出异常
// SoapFault - faultcode: 'soap:Server' faultstring: 'Fault: java.lang.NullPointerException' faultactor: 'null' detail: null
//
// XXX 只要设置一个属性的namespace, 其他属性就可以不设置了
info.namespace = NAMESPACE;
break;
case 1:
info.name = "name";
info.type = PropertyInfo.STRING_CLASS;
info.namespace = NAMESPACE;
break;
default:
break;
}
}
@Override
public void setProperty(int index, Object value) {
// XXX 可以不实现?
// switch (index) {
// case 0:
// setId(Integer.valueOf(value.toString()));
// break;
// case 1:
// setName(value.toString());
// break;
// default:
// break;
// }
}
}
/*
* copyright
*/
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import com.ufologist.model.stub.Foo_;
/**
* 测试通过KSOAP2远程调用含自定义类型参数的WebService方法
*
* @author Sun
* @version 1.0 2012-9-8
* @see http://seesharpgears.blogspot.in/2010/10/ksoap-android-web-service-tutorial-with.html
* @see http://code.google.com/p/ksoap2-android/wiki/CodingTipsAndTricks#sending/receiving_array_of_complex_types_or_primitives
* @see http://ksoap2.sourceforge.net/doc/api/
*/
public class Main {
/**
* web service服务的命名空间, 可以在wsdl(wsdl:definitions节点targetNamespace属性)中找到
* 例如:
* <wsdl:definitions targetNamespace="http://communication.service.server">
*/
private final String NAMESPACE = "http://communication.service.server";
/**
* 测试用的web service方法的实现
* 例如:
* public Foo helloFoo(Foo foo) {
* foo.setId(foo.hashCode());
* return foo;
* }
*/
private final String METHOD_NAME = "helloFoo";
/**
* web service服务地址
*/
private final String URL = "http://localhost:8080/xfiredemo/services/demo";
public static void main(String[] args) {
new Main().testKsoap2InvokeWs();
}
private void testKsoap2InvokeWs() {
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
// 设置要调用的web service方法的参数
Foo_ foo = new Foo_();
foo.setName("远程调用含自定义类型参数的WebService方法");
PropertyInfo argument = new PropertyInfo();
// web service实现方法中参数的名称
argument.setName("foo");
argument.setValue(foo);
// 如果要调用的web service方法有自定义类型参数,
// 建议设置参数的命名空间(如果在参数序列化实现类Foo_的属性中已经指定了命名空间, 省略似乎没什么影响, 但推荐指定)
argument.setNamespace(Foo_.NAMESPACE);
argument.setType(Foo_.class);
request.addProperty(argument);
// 设置web sevice SOAP envelope
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
// 映射调用WebService要传递的序列化类对象
// namespace和name就是wsdl中定义的complexType, clazz指定要序列化的类对象
envelope.addMapping(Foo_.NAMESPACE, "Foo", Foo_.class);
HttpTransportSE httpTransport = new HttpTransportSE(URL);
// debug为true时调用httpTransport.requestDump/responseDump才有值,
// 否则为null, 可以将生成的SOAP协议全部打印出来以供排错
httpTransport.debug = true;
try {
httpTransport.call(null, envelope);
// <v:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:d="http://www.w3.org/2001/XMLSchema" xmlns:c="http://schemas.xmlsoap.org/soap/encoding/" xmlns:v="http://schemas.xmlsoap.org/soap/envelope/">
// <v:Header />
// <v:Body>
// <helloFoo xmlns="http://communication.service.server" id="o0" c:root="1">
// <n0:foo i:type="n0:Foo" xmlns:n0="http://model.ufologist.com">
// <n0:id i:type="d:int">0</n0:id>
// <n0:name i:type="d:string">&#36828;&#31243;WebService&#26041;</n0:name>
// </n0:foo>
// </helloFoo>
// </v:Body>
// </v:Envelope>
System.out.println(httpTransport.requestDump);
// <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
// <soap:Body>
// <ns1:helloFooResponse xmlns:ns1="http://communication.service.server">
// <ns1:out>
// <id xmlns="http://model.ufologist.com">5784348</id>
// <name xmlns="http://model.ufologist.com">杩滅▼璋冪敤鍚刉ebService鏂规硶</name>
// </ns1:out>
// </ns1:helloFooResponse>
// </soap:Body>
// </soap:Envelope>
System.out.println(httpTransport.responseDump);
// WebService方法返回的自定义类型对象表现为SoapObject, 类似动态JavaBean
// TODO 这里是否也可以映射为自定义对象, 采用强类型来获取返回数据
SoapObject response = (SoapObject) envelope.getResponse();
// 获取属性值
System.out.println(response.getProperty("id"));
System.out.println(response.getProperty("name"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@bingshanguxue
Copy link

感谢分享。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment