google为ndroid平台开发web service提供了支持,提供了ksoap2-android相关架包
1.下载该夹包可以直接登录http://code.google.com/p/ksoap2-android/,现在该站点已经提供了直接的下载,只要点击下载链接就可以下载了;
我现在的是ksoap2-android-assembly-2.6.5-jar-with-dependencies.jar
2.好了,现在我们就可以进行新建项目来进行测试了,首先我们先建立java服务端,这里的一些前期准备我就不说了(比如与spring的整合等示例),
由于这里重点是android客户端,java服务器端就直接给代码了
interface:(这里提供了两个方法,一个传递的是简单字符串,另一个传递的是符合对象+集合)
复制代码 代码如下:
package xidian.sl.service.webservice;
import javax.jws.webparam;
import javax.jws.webservice;
import javax.jws.soap.soapbinding;
import javax.jws.soap.soapbinding.style;
import xidian.sl.service.impl.webservice.studentlist;
@webservice
@soapbinding(style = style.rpc)
public interface testservice {
public string getuser(@webparam(name = "name")string name);
public studentlist getstulist();
}
implement:
复制代码 代码如下:
package xidian.sl.service.impl.webservice;
import java.util.arraylist;
import java.util.list;
import javax.jws.webservice;
import xidian.sl.entity.students;
import xidian.sl.service.webservice.testservice;
@webservice(endpointinterface = "xidian.sl.service.webservice.testservice")
public class testserviceimpl implements testservice {
@override
public string getuser(string name) {
system.out.println("客户端传递的名字为 = "+name);
return name;
}
@override
public studentlist getstulist() {
system.out.println("该方法被调用");
list<students> stulist = new arraylist<students>();
//第一个学生
students stu1 = new students();
stu1.setstuname("沈浪");
stu1.setstunum("1006010054");
stu1.setstusex("男");
stulist.add(stu1);
//第二个学生
students stu2 = new students();
stu2.setstuname("香香");
stu2.setstunum("1006010043");
stu2.setstusex("女");
stulist.add(stu2);
//将list集合封装成一个对象才能在webservice中进行传递
studentlist studentlist = new studentlist();
studentlist.setstulist(stulist);
return studentlist;
}
}
list的封装对象
复制代码 代码如下:
package xidian.sl.service.impl.webservice;
import java.util.list;
import xidian.sl.entity.students;
public class studentlist {
private list<students> stulist;
public list<students> getstulist() {
return stulist;
}
public void setstulist(list<students> stulist) {
this.stulist = stulist;
}
}
然后在srping的整合配置文件中进行如下配置即可(默认web.xml中已经进行配置)
复制代码 代码如下:
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemalocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:meta-inf/cxf/cxf.xml" /> <!-- 这些xml文件在cxf-2.5.0.jar的meta-inf目录下-->
<!--<import resource="classpath:meta-inf/cxf/cxf-extension-soap.xml" />
警告提示已经废弃了cxf-extension-soap.xml文件-->
<import resource="classpath:meta-inf/cxf/cxf-servlet.xml" />
<!-- 这里配置服务接口,后面描述
id:指在spring配置的bean的id.
implementor:指明具体的实现类.
address:指明这个web service的相对地址
-->
<!-- 测试 -->
<bean id="testserviceimpl" class="xidian.sl.service.impl.webservice.testserviceimpl" >
</bean>
<jaxws:endpoint id="testservice"
implementor="#testserviceimpl"
address="/test" />
<!-- 开启tomcat服务器 ,访问http://localhost:8080/webexam/services/test?wsdl
http://localhost:8080/webexam是本项目的访问地址
services是由于web.xml配置所得,test是由于spring配置文件中的address属性所得
-->
</beans>
3.到此服务器端的已经建立完全,我们可以测试下:开启tomcat,然后在浏览器中输入http://localhost:8090/webexam/services/test?wsdl可以查看wsdl
现在我们就可以开始建立android客户端了
新建一个项目后导入ksoap2-android-assembly-2.6.5-jar-with-dependencies.jar,这里要特别注意:导入包的方式不要选择项目右键---->build path---->
add external archives...,如果使用这种方式表面上好像是导入了包,但还是没有办法引用到,然后启动项目后一直会报:
我们还是选择和开发web一样的方式,就是在项目下新建lib或者libs文件夹,然后将jar直接复制到该文件夹中,ide会帮助直接引入的:
这样就正确无误了,不再会报类无法引用到了
android中通过webservice调用服务器端其实还是很简单的,只要按部就班的按照下面步骤进行即可:
(1)创建httptransportse对象,该对象用于调用webservice操作
复制代码 代码如下:
httptransportse ht = new httptransportse(service_url);
(2)创建soapserializationenvelope对象
复制代码 代码如下:
soapserializationenvelope envelope = new soapserializationenvelope
(soapenvelope.ver11);
(3)创建soapobject对象,创建该对象时需要传入所要调用的web service的命名空间和webservice方法名
复制代码 代码如下:
soapobject request = new soapobject(service_ns, methodname);
(4)如果有参数传给web service服务器端,调用soapobject对象的addproperty(string name, object value)方法来设置参数,该方法的name参数指定参数名
注意:参数名不一定要与服务端的方法中的参数名相同,只要对应顺序相同即可;value参数指定参数值
复制代码 代码如下:
request.addproperty("name", "1006010054");
(5)调用soapserializationenvelope的setoutputsoapobject()方法,或者直接对bodyout属性赋值,将前两步创建的soapobject对象设为soapserializationenvelope的传出soap消息体
复制代码 代码如下:
envelope.bodyout = request;
(6)调用对象的call()方法,并以soapserializationenvelope作为参数调用远程的web service
复制代码 代码如下:
ht.call(null, envelope);
(7)掉用完成后,访问soapserializationenvelope对象的bodyin属性,该属性返回一个soapobject对象,该对象就代表web service的返回消息,解析该对象,即可获得调用web service的返回值
复制代码 代码如下:
soapobject result = (soapobject) envelope.bodyin;
string name = result.getproperty(0).tostring();
下面给书具体的实例:
mian.xml很简单就是两个编辑框:
复制代码 代码如下:
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<textview
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<edittext
android:id="@+id/edittext1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" >
<requestfocus />
</edittext>
<edittext
android:id="@+id/edittext2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" />
</linearlayout>
activity:(该activity调用了服务器端返回普通字符串的方法)
复制代码 代码如下:
package xidian.sl.android.webservice;
import org.ksoap2.soapenvelope;
import org.ksoap2.serialization.soapobject;
import org.ksoap2.serialization.soapserializationenvelope;
import org.ksoap2.transport.httptransportse;
import android.app.activity;
import android.os.bundle;
import android.widget.edittext;
public class webservicesimpledemo extends activity{
final static string service_ns = "http://webservice.service.sl.xidian/";
final static string service_url = "http://192.168.1.103:8090/webexam/services/test";
private edittext txt1;
private edittext txt2;
/** called when the activity is first created. */
@override
public void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.main);
txt1 = (edittext) findviewbyid(r.id.edittext1);
txt2 = (edittext) findviewbyid(r.id.edittext2);
//调用的方法
string methodname = "getuser";
//创建httptransportse传输对象
httptransportse ht = new httptransportse(service_url);
ht.debug = true;
//使用soap1.1协议创建envelop对象
soapserializationenvelope envelope = new soapserializationenvelope(soapenvelope.ver11);
//实例化soapobject对象
soapobject request = new soapobject(service_ns, methodname);
/**
* 设置参数,参数名不一定需要跟调用的服务器端的参数名相同,只需要对应的顺序相同即可
* */
request.addproperty("name", "1006010054");
//将soapobject对象设置为soapserializationenvelope对象的传出soap消息
envelope.bodyout = request;
try{
//调用webservice
ht.call(null, envelope);
//txt1.settext("看看"+envelope.getresponse());
if(envelope.getresponse() != null){
txt2.settext("有返回");
soapobject result = (soapobject) envelope.bodyin;
string name = result.getproperty(0).tostring();
txt1.settext("返回值 = "+name);
}else{
txt2.settext("无返回");
}
}catch (exception e) {
e.printstacktrace();
}
}
}
在androidmanifest.xml进行activity的注册和并添加访问网络的权限
复制代码 代码如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xidian.sl.android.webservice"
android:versioncode="1"
android:versionname="1.0" >
<uses-sdk android:minsdkversion="10" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".webservicesimpledemo"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.main" />
<category android:name="android.intent.category.launcher" />
</intent-filter>
</activity>
</application>
<!-- 声明该应用自身所拥有的权限 -->
<uses-permission android:name="android.permission.internet" />
</manifest>
运行后的结果如图所示:
下面我们来试着调用回传符合对象的方法:
activity:
复制代码 代码如下:
package xidian.sl.android.webservice;
import org.ksoap2.soapenvelope;
import org.ksoap2.serialization.soapobject;
import org.ksoap2.serialization.soapserializationenvelope;
import org.ksoap2.transport.httptransportse;
import android.app.activity;
import android.os.bundle;
import android.widget.edittext;
public class webservicecomplexdemo extends activity{
final static string service_ns = "http://webservice.service.sl.xidian/";
final static string service_url = "http://192.168.1.103:8090/webexam/services/test";
private edittext txt1;
private edittext txt2;
/** called when the activity is first created. */
@override
public void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.main);
txt1 = (edittext) findviewbyid(r.id.edittext1);
txt2 = (edittext) findviewbyid(r.id.edittext2);
//调用的方法
string methodname = "getstulist";
//创建httptransportse传输对象
httptransportse ht = new httptransportse(service_url);
ht.debug = true;
//使用soap1.1协议创建envelop对象
soapserializationenvelope envelope = new soapserializationenvelope(soapenvelope.ver11);
//实例化soapobject对象
soapobject request = new soapobject(service_ns, methodname);
/**
* 设置参数,参数名不一定需要跟调用的服务器端的参数名相同,只需要对应的顺序相同即可
* */
//request.addproperty("name", "1006010054");
//将soapobject对象设置为soapserializationenvelope对象的传出soap消息
envelope.bodyout = request;
try{
//调用webservice
ht.call(null, envelope);
txt2.settext("回传的值 :"+envelope.getresponse());
if(envelope.getresponse() != null){
soapobject result = (soapobject) envelope.bodyin;
soapobject soapchilds = (soapobject)result.getproperty(0);
stringbuffer sb = new stringbuffer();
for(int i=0; i <soapchilds.getpropertycount(); i++){
soapobject soapchildschilds = (soapobject)soapchilds.getproperty(i);
sb.append("姓名["+i+"] = "+soapchildschilds.getproperty(0).tostring()+"\n");
sb.append("学号["+i+"] = "+soapchildschilds.getproperty(1).tostring()+"\n");
sb.append("性别["+i+"] = "+soapchildschilds.getproperty(2).tostring()+"\n"+"\n");
}
txt1.settext(sb.tostring());
}else{
txt1.settext("无返回");
}
}catch (exception e) {
e.printstacktrace();
}
}
}
区别就是对于返回值的处理上,使用几次getpropert()方法,这里主要看返回值的层次,看下面的结果应该就能明白了,根据括号的层次来进行确定