Android环境下Ksoap连接Axis2

1 开发环境

OS :  win7  32bit

Axis2 :  1.6.2

Ksoap :  2.0

Android: 4.0.3

 

2 基于Axis2的服务器端开发

2.1文件下载

首先需要下载 axis2 的相关jar 包,到 axis 的官方网站即可获得开发的依赖包。 下载地址:

http://axis.apache.org/axis2/java/core/download.cgi

现在最高的版本是1.6.2的,下载axis2-1.6.2-bin.zip和axis2-1.6.2-war.zip压缩文件。 然后需要下载官方提供的axis 的 eclipse 插件工具:ServiceArchive Wizard - Eclipse Plug-in 和CodeGenerator Wizard - Eclipse Plug-in。这些工具可以帮助我们打包(aar)及其生产 客户端调用代码。 下载页面:

http://axis.apache.org/axis2/java/core/tools/index.html

 

2.2 Axis2安装与测试

·        安装插件

    将ServiceArchive Wizard - Eclipse Plug-in和Code GeneratorWizard - Eclipse Plug-in插件的压缩文件解压,然后将plugins文件夹中的jar文件放入eclipse下的plugins文件夹下,重启eclipse。如果你的 eclipse 插件安装成功后,打开elipse后New->Other会看到如下效果:

 

·        部署 axis2

    我们需要将下载下来的axis2-1.6.2-war.zip 中的 axis2.war 这个文件放在我们的tomcat安装 目录下的webapps目录下,启动 tomcat 就会把 war 文件转成一个可以跑起来的 axis2 的项目。Tomcat启动后,在浏览器中输入:http://localhost:8080/axis2/ 可以看到如下界面:



2.3 开发与部署WebService

²  建立一个Java工程,命名为XitianServer;

²  新建一个package,命名为com.wisu.service;

²  新建一个主类(BusinessOperateService.java),一个请求代理类(BusinessProxyRequest.java),一个结果返回代理类(BusinessProxyResponse.java),错误信息类(GenericFault.java)和一个错误类型定义接口(FalutType.java)

²  在工程中新建一个lib文件夹,将与axis2相关的jar文件都包含进去

 

BusinessOperateService.java

public class BusinessOperateService implements FaultType {
   
    publicBusinessProxyResponse businessOperate(BusinessProxyRequest request){
        //设置返回的对象
        BusinessProxyResponse response = newBusinessProxyResponse();   
       
        GenericFault gen = newGenericFault();
        gen.setCode(success);                //设置结果代码
        gen.setErrorMessage("OK");          //设置处理结果详细信息
       
        String result =  "<customer>" +
                         "<person>" +
                             "<customerNumber>100</customerNumber>" +
                             "<firstName>真鲜</firstName>" +
                             "<lastName>一鸣</lastName>" +
                         "</person>" +
                         "<street>西斗门路</street>" +
                         "<city>杭州</city>" +
                         "<state>中国</state>" +
                         "<zip>1010</zip>" +
                         "<phone>0577-110</phone>" +
                         "</customer>";    //设置返回的XML报文
        //封装返回结果
        response.setResultXML(result);  
        response.setGenericFault(gen);
        returnresponse;
    }
}

BusinessProxyRequest.java

public class BusinessProxyRequest {
 
    private StringbusinessID;    //业务ID值
    private StringbusinessType;  //业务类型
    private StringbusinessXML;   //XML请求报文
 
    /**省略了set和get方法**/
}
 

BusinessProxyResponse.java

public class BusinessProxyResponse {
 
    private StringresultXML;           //结果XML报文
    privateGenericFault genericFault;   //错误信息
   
    /**省略了set和get方法**/
} 


GenericFault.java

public class GenericFault {
    private int code;               //错误代码
    private StringerrorMessage;   //错误消息
   
    /**省略了set和get方法**/
}

FaultType.java

interface FaultType {
    final int success =0;         //处理成功
    final int interiorError = -1;  //内部错误
}


2.4 打包生生aar文件来发布WebService服务

(1) 选择New->Other,然后选择客户端代码生成工具Axis2 widzards下的Axis2 code generator,点击Next。


(2) 选择Axis2 Service Archiver然后点击 Next

(3)在Class File Location中填写:E:\workspace\XitianServer\bin,勾选Include.class files only选项,点击next



(4)选择Skip WSDL选项,点击next:

 

(5)不做任何处理;

 

 

(7) 填写服务名称(Service name,自定义)和类的名称(Class name,包名称+Java类的类名),然后单击load按钮,勾选所要的方法;

 

(8) 填写aar文件输出路径(Output file location)和aar文件名称(OutputFile Name),然后点击Finish按钮,完成服务的打包;

 

(9) 将aar包放在E:\apache-tomcat-7.0.47\webapps\axis2\WEB-INF\services路径下,重启Tomcat,在http://localhost:8080/axis2/services/listServices下就可以看到新发布的服务:



3 基于Android的客户端开发

²  新建一个Android工程,命名为XitianClient,Activity所在的Package为:com.wisu.xitiancheng.dao;

²  新建一个Activity,命名为MainActivity;

²  新建一个Package,在Package下新建BusinessProxyRequest.java,BusinessProxyResponse.java,GenericFault.java和CastObject.java,在Android运行环境下,同过Soap发送的自定义类参数和接收的类参数都需要通过实现KvmSerializable接口来进行序列化,自定义类中的成员类变量所指向的类也是需要进行序列化,如GenericFault.java

²  新建一个文件夹add_lib,加入Ksoap的支持包:ksoap2-android-assembly-3.1.1-jar-with-dependencies.jar,并将add_lib文件夹上选择右击,在Build Path中选择将文件夹设置为Use as SourceFolder ;

²  增加Http通讯权限,在工程下的AndroidManifest.xml中加入以下权限:

    <uses-permissionandroid:name="android.permission.CAMERA"/>
    <uses-permissionandroid:name="android.permission.VIBRATE"/>
    <uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permissionandroid:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
    <uses-permissionandroid:name="android.permission.READ_PHONE_STATE"/>
    <uses-permissionandroid:name="android.permission.INTERNET"/>
    <uses-permissionandroid:name="android.permission.RECEIVE_SMS"/>
    <uses-permissionandroid:name="android.permission.RECORD_AUDIO"/>
    <uses-permissionandroid:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
    <uses-permissionandroid:name="android.permission.READ_CONTACTS"/>
    <uses-permissionandroid:name="android.permission.WRITE_CONTACTS"/>
    <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>

工程结构图:



MainActivity.java

public class MainActivity extendsActivity {
TextView tv;
//发布服务的命名空间
   private static final StringNAME_SPACE ="http://service.wisu.com";   
  //BusinessProxyRequest的命名空间,定义了BusinessProxyRequest里的成员变量
private static final StringNAME_SPACE2 ="http://service.wisu.com/xsd";     
private static final StringWDSL_LINK ="http://192.168.2.133:8080/axis2/services/BusinessOperateService?wsdl";   //服务路径
    private static final StringMETHOD_NAME ="businessOperate";    //方法名称
   
    @Override
    public voidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv =(TextView)findViewById(R.id.xml_content);
       
        //开辟一个请求线程
        Thread thr = newThread() {
        public void run(){
            try { 
              StringrequestStr =  "<customer>" +
                         "<person>" +
                             "<customerNumber>100</customerNumber>" +
                             "<firstName>真鲜</firstName>" +
                             "<lastName>一鸣</lastName>" +
                         "</person>" +
                         "<street>西斗门路</street>" +
                         "<city>杭州</city>" +
                         "<state>中国</state>" +
                         "<zip>1010</zip>" +
                         "<phone>0577-110</phone>" +
                         "</customer>";    //请求XML报文              
             
            String businessID = "bid001";
            String businessType = "Test";
               
            //封装请求
            BusinessProxyRequest request = newBusinessProxyRequest();
            request.setBusinessID(businessID);
            request.setBusinessType(businessType);
            request.setBusinessXML(requestStr);
               
            //将自定义类对象序列化
            PropertyInfo pi = newPropertyInfo();
            pi.setName("request");                 //必须和webservice中的参数名称一致
            pi.setValue(request);
            pi.setType(BusinessProxyRequest.class);            
               
            //封装Soap请求对象
        SoapObjectsoaprequest = new SoapObject(NAME_SPACE,METHOD_NAME);
        soaprequest.addProperty(pi);      
            
        SoapSerializationEnvelopeenvelope =new SoapSerializationEnvelope(SoapEnvelope.VER11); 
            envelope.bodyOut =soaprequest;   //报文体
            envelope.dotNet = false;   //是否为dotNet服务
            envelope.setOutputSoapObject(soaprequest); 
            envelope.addMapping(NAME_SPACE2,"BusinessProxyRequest", request.getClass());   //将请求的BusinessProxyRequest与服务器端的BusinessProxyRequest进行相互映射
            envelope.avoidExceptionForUnknownProperty =true;
               
            HttpTransportSE ht = newHttpTransportSE(WDSL_LINK);   //建立HTTP连接
               
            ht.call("urn:businessOperate", envelope);     //调用WebService的服务           
               
            SoapObject result = (SoapObject)envelope.getResponse();    //获得服务返回结果
            try {
             //解析BusinessProxyResponse对象
            BusinessProxyResponse response =(BusinessProxyResponse) CastObject.parseToObject(result,BusinessProxyResponse.class);   //将SoapObject对象转化为BusinessProxyResponse
             tv.setText(response.getResultXML()); 
             SoapObject generic = (SoapObject)response.getGenericFault();
                 
             //解析GenericFault对象
             GenericFault genericFault =(GenericFault) CastObject.parseToObject(generic, GenericFault.class);   //将SoapObject对象转化为GenericFault
             Log.d("Code: ",String.valueOf(genericFault.getCode()));
             Log.d("ErrorMessage: " , genericFault.getErrorMessage());
                 
            }catch (IllegalAccessException e) {
               e.printStackTrace();
            }catch (InstantiationException e) {
               e.printStackTrace();
            }
             } catch(SoapFault e) { 
                    e.printStackTrace(); 
             } catch(IOException e) { 
                    e.printStackTrace(); 
             } catch(XmlPullParserException e) { 
                    e.printStackTrace(); 
             } 
        }
        };
        thr.start();
        try {
           Thread.sleep(500);    //一定需要加休眠时间,否则会发生请求错误,不知道基于什么原理
       }catch (InterruptedException e) {
           e.printStackTrace();
       }
    }
  
}

BusinessProxyRequest.java

public class BusinessProxyRequest implements KvmSerializable{
    private StringbusinessID;    //业务ID值
    private StringbusinessType;  //业务类型
    private StringbusinessXML;   //XML请求报文
    private static final StringNAME_SPACE2 ="http://service.wisu.com/xsd";
 
    @Override
    public ObjectgetProperty(int arg0) {
       Objectres = null;
       switch(arg0){
       case 0:
           res= this.businessID;
           break;
       case 1:
           res= this.businessType;
           break;
       case 2:
           res= this.businessXML;
           break;
       default:
           break;    
       }
       return res;
    }
    @Override
    public int getPropertyCount() {
       return 3;
    }
    @Override
    public voidgetPropertyInfo(int arg0,Hashtable arg1, PropertyInfo arg2) {
       switch(arg0){
       case 0:
           arg2.type =PropertyInfo.STRING_CLASS;
           arg2.name = "businessID";
           arg2.namespace = NAME_SPACE2;
           break;
       case 1:
           arg2.type =PropertyInfo.STRING_CLASS;
           arg2.name = "businessType";
           arg2.namespace = NAME_SPACE2;
           break;
       case 2:
           arg2.type =PropertyInfo.STRING_CLASS;
           arg2.name = "businessXML";
           arg2.namespace = NAME_SPACE2;
           break;
       default:
           break;
       }
    }
 
    @Override
    public voidsetProperty(int arg0, Object arg1) {
       if(arg1== null)return;
       switch(arg0){
       case 0:
           this.businessID =arg1.toString();
           break;
       case 1:
           this.businessType =arg1.toString();
           break;
       case 2:
           this.businessXML =arg1.toString();
           break;
       default:
           break;
       }
    }
 
    public StringgetBusinessID() {
       return businessID;
    }
 
    public voidsetBusinessID(String businessID) {
       this.businessID =businessID;
    }
 
    public StringgetBusinessType() {
       return businessType;
    }
 
    public voidsetBusinessType(String businessType) {
       this.businessType =businessType;
    }
 
    public StringgetBusinessXML() {
       return businessXML;
    }
 
    public voidsetBusinessXML(String businessXML) {
       this.businessXML =businessXML;
    }
   
}
 

BusinessProxyResponse.java

public class BusinessProxyResponse implements KvmSerializable {
 
    private StringresultXML;     //结果XML报文
    private ObjectgenericFault;  //错误信息
   
    public voidsetResultXML(String resultXML) {
       this.resultXML =resultXML;
    }
   
    public StringgetResultXML() {
       return resultXML;
    }
   
    public voidsetGenericFault(GenericFault genericFault) {
       this.genericFault =genericFault;
    }
   
    public ObjectgetGenericFault() {
       return genericFault;
    }
 
    @Override
    public ObjectgetProperty(int arg0) {
       Objectres = null;
        switch(arg0){
       case 0:
           res= this.resultXML;
           break;
       case 1:
           res= this.genericFault;
           break;
       default:
           break;    
       }
       return res;
    }
 
    @Override
    public intgetPropertyCount() {
       return 2;
    }
 
    @Override
    public voidgetPropertyInfo(int arg0,Hashtable arg1, PropertyInfo arg2) {
       switch(arg0){
       case 0:
           arg2.type =PropertyInfo.STRING_CLASS;
           arg2.name = "resultXML";
           break;
       case 1:
           arg2.type =PropertyInfo.OBJECT_CLASS;
           arg2.name = "genericFault";
           break;
       default:
           break;
       }
    }
 
    @Override
    public voidsetProperty(int arg0, Object arg1) {
       if(arg1== null)return;
       switch(arg0){
       case 0:
           this.resultXML =arg1.toString();
           break;
       case 1:
           this.genericFault =arg1;
           break;
       default:
           break;
       }
    }
      
}

GenericFault.java

public class GenericFault implements KvmSerializable{
 
    private int code;               //错误代码
    private StringerrorMessage;   //错误消息
   
    public voidsetCode(int code) {
       this.code =code;
    }
   
    public intgetCode() {
       return code;
    }
   
    public voidsetErrorMessage(String errorMessage) {
       this.errorMessage =errorMessage;
    }
   
    public StringgetErrorMessage() {
       return errorMessage;
    }
 
    @Override
    public ObjectgetProperty(int arg0) {
       // TODO Auto-generated method stub
       Objectres = null;
       switch(arg0){
       case 0:
           res= this.code;
           break;
       case 1:
           res= this.errorMessage;
           break;
       default:
           break;    
       }
       return res;
    }
 
    @Override
    public intgetPropertyCount() {
       return 2;
    }
 
    @Override
    public voidgetPropertyInfo(int arg0,Hashtable arg1, PropertyInfo arg2) {
       switch(arg0){
       case 0:
           arg2.type =PropertyInfo.INTEGER_CLASS;
           arg2.name = "code";
           break;
       case 1:
           arg2.type =PropertyInfo.STRING_CLASS;
           arg2.name = "errorMessage";
           break;
       default:
           break;
       }
    }
 
    @Override
    public voidsetProperty(int arg0, Object arg1) {
       if(arg1== null)return;
       switch(arg0){
       case 0:
           this.code =(Integer)arg1;
           break;
       case 1:
           this.errorMessage =arg1.toString();
           break;
       default:
           break;
       }
    }
}
 

CastObjcet.java

public class CastObject {
   
    public staticKvmSerializable parseToObject(SoapObject soapObject, Class objectClass)throwsIllegalAccessException, InstantiationException{
 
       KvmSerializableresult = (KvmSerializable) objectClass.newInstance();
 
       intnumOfAttr = result.getPropertyCount();
 
       for(int i=0;i<numOfAttr; i++){
           PropertyInfo info = newPropertyInfo();
           result.getPropertyInfo(i, null,info);
 
           //处理property不存在的情况
           try{
               result.setProperty(i,soapObject.getProperty(info.name));
           }catch(Exceptione){
               continue;
           }
       }
       returnresult;
    }
}


4 XML字符串解析

4.1 目标XML字符串

    <customer>
        <person>
            <customerNumber>100</customerNumber>
            <firstName>真鲜</firstName>
            <lastName>一鸣</lastName>
        </person>
        <street>西斗门路</street>
        <city>杭州</city>
        <state>中国</state>
        <zip>1010</zip>
        <phone>0577-110</phone>
    </customer> 

对应的Java类

Person.java

public class Person{
        private StringcustomerNumber;
        private StringfirstName;
       private StringlastName;
 
/*省略了set和get方法*/
}

Customer.java

public classCustomer {
        private Personperson;
        private Stringstreet;
        private Stringcity;
        private Stringstate;
        private Stringzip;
        private Stringphone;
 
 /*省略了set和get方法*/
}
 

4.2 Jibx解析

Jibx的优点在于解析的速度快,编码量少,但是使用Jibx需要引入额外的Jar包,这在服务器端开发不成问题,但是在Android端开发时会增加apk的大小。另外使用Jibx需要手动进行编译相关class和XML文件,需要做不少前期工作,而开发过程中只需要写不到10行的代码就行了。

²  在终端进入到工程所在目录,如E:\workspace\XitianServer;

²  运行:java -cp bin;E:/开源项目/jar/jibx/jibx-tools.jar;E:/开源项目/jar/jibx/log4j-1.2.16.jar org.jibx.binding.generator.BindGen-b Customer.xml com.wisu.model.Customer;其中E:/开源项目/jar/jibx/ 为jibx-tools.jar的路径,Cutomer.xml是生成的XML的名称,com.wisu.model.Customer 为Customer.class的路径;

²  打开Customer.xml,去掉<namespace uri="http://iap.com/dal" default="elements"/>,并将<mapping abstract="true"type-name="ns1:customer" class="com.iap.dal.Customer"></binding>里的内容移动到 <mapping class="com.iap.dal.Customer"name="customer"></mapping>之间

²  运行:java -cpbin;E:/开源项目/jar/jibx/jibx-bind.jarorg.jibx.binding.Compile -v Customer.xml ,在bin/com/wisu/model/目录下增加了JiBX_CustomerCustomer_access.class 和 JiBX_CustomerFactory.class两个文件。

 

/**

 *使用Jibx解析XML字符串

 */

public class BusinessOperateService implements FaultType{
   
    publicBusinessProxyResponse businessOperate(BusinessProxyRequest request){
      
        BusinessProxyResponse response = newBusinessProxyResponse();   //设置返回的对象
       
        try {
            InputStream reader =String2InputStream(request.getBusinessXML());
           IBindingFactory factory = BindingDirectory.getFactory(Customer.class);
           IUnmarshallingContext uctx =factory.createUnmarshallingContext();
          
           Customer customerMessage =(Customer)uctx.unmarshalDocument(reader, null);
           Person messageBody =customerMessage.getPerson();
          
           System.out.println("CustomerNumber: " + messageBody.getCustomerNumber());
           System.out.println("FirstName: " + messageBody.getFirstName());
           System.out.println("LastName: " + messageBody.getLastName());
           System.out.println("City: " + customerMessage.getCity());
          
        } catch(JiBXException e) {
           e.printStackTrace();
        } catch(UnsupportedEncodingException e) {
           e.printStackTrace();
       }  
 
        returnresponse;
    }
   
   
    /**
     *将String类型转化为InputStream并设置为UTF-8编码
     */
    publicInputStream String2InputStream(String str)throwsUnsupportedEncodingException
    {
       ByteArrayInputStreamstream = new ByteArrayInputStream(str.getBytes("UTF-8"));
        returnstream;
    }
}

4.3 Sax解析

    Sax是目前主流的解析方式,不需要第三方插件的支持,速度较快,但是需要开发人理解XML结构的逻辑性并需要编写大量的代码。

/**
 *使用Sax解析XML字符串
 */
public class SAXXmlService extendsDefaultHandler {
   
    private Personperson;
    privateCustomer customer;
    private StringcurrentTag;   //当前所解析的标签
   
    public staticCustomer getPersonInfo(String xmlStr) throwsParserConfigurationException, SAXException, IOException{
      
       SAXParserFactoryfactory = SAXParserFactory.newInstance();
        SAXParser saxParser =factory.newSAXParser();
       InputStreaminputStr = String2InputStream(xmlStr);   //将String转化为InputStream类型
       SAXXmlServicehandler = new SAXXmlService();
       saxParser.parse(inputStr,handler);
        inputStr.close();
 
        returnhandler.customer;
    }
   
   
    /**
     *将String转化为InputStreeam类型
     */
    public staticInputStream String2InputStream(String str) throwsUnsupportedEncodingException
    {
       ByteArrayInputStreamstream = new ByteArrayInputStream(str.getBytes("UTF-8"));
        returnstream;
    }
   
    public voidcharacters(char[] ch,int start, int length)throws SAXException { 
        super.characters(ch,start, length); 
       
        // 判断当前标签是否有效 
        if (currentTag !=null){ 
            // //读取标签里面的内容 
            String value = newString(ch, start, length); 
            // 如果是Id标签,则读取Id标签的内容设置到Person的ID值上 
            if ("customerNumber".equalsIgnoreCase(currentTag)){ 
                person.setCustomerNumber(value);
            } else if ("firstName".equalsIgnoreCase(currentTag)) {//firstName标签 
                person.setFirstName(value);
            } else if ("lastName".equalsIgnoreCase(currentTag)) {// lastName标签 
                person.setLastName(value); 
            } else if ("street".equalsIgnoreCase(currentTag)){ // street标签 
                customer.setStreet(value);
            } else if ("city".equalsIgnoreCase(currentTag)) {
              customer.setCity(value);
            } else if ("state".equalsIgnoreCase(currentTag)) {
              customer.setState(value);
            } else if ("zip".equalsIgnoreCase(currentTag)) {
              customer.setZip(value);
            } else if ("phone".equalsIgnoreCase(currentTag)) {
              customer.setPhone(value);
            }
        } 
    } 
 
    /** 
     * 解析XML时,当读到结束一个元素标签时 
     */   
    public voidendElement(String uri, String localName, String qName) throwsSAXException { 
        super.endElement(uri,localName, qName); 
       
        // 将当前标签名置空 
        currentTag = null; 
        // 如果当前结束的标签名是person的话,代表一个person对象已经读取完毕。将其添加到list后置空 
        if(qName.equals("person")) { 
           customer.setPerson(person);
        } 
        if(qName.equals("customer")) {
       
        }
    } 
 
    /** 
     * 解析XML时,当开始读取XML文档时 
     */  
    public voidstartDocument() throws SAXException { 
        super.startDocument();  
       
    } 
 
    /** 
     * 解析XML时,当开始读到一个元素标签开始时 
     */  
    public voidstartElement(String uri, String localName, String qName, Attributes attributes)throws SAXException { 
        super.startElement(uri,localName, qName, attributes); 
        if(qName.equals("person")) { 
           person = new Person();     
        } 
        if(qName.equals("customer")) {
        customer = newCustomer();
        }
        currentTag =qName; 
    } 
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值