Created
September 8, 2012 15:20
-
-
Save ufologist/3675931 to your computer and use it in GitHub Desktop.
怎样通过ksoap2发送复杂参数给web service方法(How to send complex type using ksoap2)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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; | |
// } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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">远程WebService方</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(); | |
} | |
} | |
} |
完整实现的代码可参考: http://sunlab.googlecode.com/svn/trunk/ksoap2-complex-type-example/
非常感谢他们给我带来的启发和价值
http://seesharpgears.blogspot.in/2010/10/ksoap-android-web-service-tutorial-with.html
http://code.google.com/p/ksoap2-android/wiki/CodingTipsAndTricks#sending/receiving_array_of_complex_types_or_primitives
感谢分享。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
由于在android开发中需要调用Web Service, 因此碰到个棘手的问题
How to call SOAP web service in Android, 答案就是用ksoap2
调用简单的web service方法只是传String参数so easy, 例子比比皆是, 但面对复杂类型, 没有一个非常完整的例子, 因此查阅多方资料总结了一套比较完善的例子
需求场景:
实现思路:
这个公用的项目就是简单的JavaBean, 不会依赖server端或android
特别注意: 属性为整型的应采用int而非Integer,
否则报错: SoapFault - faultcode: 'soap:Server' faultstring: 'Illegal argument. For input string: ""' faultactor: 'null' detail: null
eclipse可以设置Deployment Assembly依赖公用项目(会打包为jar放在WEB-INF/lib下)
特别注意: 设置Foo各个属性所处的命名空间(WSDL中自定义数据类型的命名空间),
否则报错: SoapFault - faultcode: 'soap:Server' faultstring: 'Fault: java.lang.NullPointerException' faultactor: 'null' detail: null
envelope.addMapping映射调用WebService要传递的序列化类对象, namespace和name就是wsdl中定义的complexType, clazz指定要序列化的类对象