Android访问WebService并保持会话

Android访问WebService并保持会话


条件建设


  • 服务端:Axis2、Tomcat7
  • 客户端:android开发环境、ksoap2*.jar

Android访问webService的方法


  对于一个完整的应用程序,若无法保存状态,就意味着webService很难完成我们的任务。幸好,axis2为我们提供了类似web应用中session和cookie的功能,即web Service中的会话管理的功能。这里参考了这个网页的做法,他提到:

 使用Axis2来管理WebService的状态基本上对于开发人员是透明的。在WebService类需要使用org.apache.axis2.context.MessageContext和org.apache.axis2.context.ServiceContext类来保存与获得保存在服务端的状态信息,这有些象使用HttpSession接口的getAttribute和setAttribute方法获得与设置Session域属性。

  与之不同的是,我们的客户端使用的android平台,无法使用axis2的jar包,但是服务端的设置是一样的:
  
1. 使用MessageContext和ServiceContext获得与设置key-value对。
2. 为要进行Session管理的WebService类所对应的元素添加一个scope属性,并将该属性值设为transportsession。
那么重要的是客户端如何访问呢?下面是我封装的一个方法:

/**
 * 
 */
package com.mapapp.subclient;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.ksoap2.HeaderProperty;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;

/**
 * @author L.M Xia @Cetc28th
 * 说明:调用远程web Service的工具类
 */
public class WebServiceUtil {
    private static HeaderProperty mSessionHeader = null;
    /**
     * 
     * @param HttpUrl 服务URL地址
     * @param MethodName 调用的服务方法名
     * @param WSNameSpace WebService命名空间
     * @param Params 方法带入的参数集
     * @return
     */
    public static String callWebServiceMethod(String HttpUrl, String MethodName,
            String WSNameSpace, HashMap<String, String> Params) {

        String result = null;//方法的返回值
        ArrayList<String> NumberList = new ArrayList<String>();
        String SOAP_ACTION = WSNameSpace + MethodName;
        SoapObject requestObject = new SoapObject(WSNameSpace, MethodName);
        if (Params != null) {
            for (Map.Entry<String,String> entry : Params.entrySet()) {
                String Number = (String)entry.getKey();//参数名
                NumberList.add(Number);
            }
            Collections.sort(NumberList);
            for (String string : NumberList) {
                String Param_Pair  = (String)Params.get(string);//参数值
                String[] Param_Name = Param_Pair.split("-");
                if (Param_Name != null) {
                    requestObject.addProperty(Param_Name[0], Param_Name[1]);
                }
            }
        }
        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                SoapEnvelope.VER11);
        envelope.dotNet = true;     //一直都是设置成true,还没试设置成false有没有问题
        envelope.bodyOut = requestObject;

        HttpTransportSE hts = new HttpTransportSE(HttpUrl);
        // web service
        Object o = null;
        try {
            LinkedList<HeaderProperty> reqHeaders = new LinkedList<HeaderProperty>();
            //若已经带有cookie,则每次访问WebService时,要带有这个cookie。
            if (mSessionHeader != null) {
                reqHeaders.add(new HeaderProperty("Cookie", mSessionHeader
                        .getValue()));
                //cookie中包含了服务端session的JsessionID。
            }
            @SuppressWarnings("rawtypes")
            List headerList = hts.call(SOAP_ACTION, envelope, reqHeaders);//访问WebService
            for (Object headerElement : headerList) {
                HeaderProperty headerProperty = (HeaderProperty) headerElement;
                String headerKey = headerProperty.getKey();
                String headerValue = headerProperty.getValue();
                System.out.println(headerKey + "->" + headerValue);
                if (headerKey != null && headerKey.equalsIgnoreCase("set-cookie")) {
                    //第一次访问时没有cookie。
                    mSessionHeader = headerProperty;//服务端发送过来的set-cookie项
                }
            }

            o = envelope.getResponse();
            result = o.toString();
        } catch (SoapFault e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        }

        return result;
    }
}

调用的接口示例:

    public String  loginWS() {
        String results = null;
        //调用web service的命名空间
        String nameSpace = "http://service.web.org";
        //调用的方法名
        String methodName = "login";
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("b", "password-1234");
        params.put("a", "username-xia");//按顺序排列a-b-c-d-...z;

        String httpUrl = "http://192.168.1.11:8080/axis2/services/ComplexTypeService";
        results = WebServiceUtil.callWebServiceMethod(httpUrl, methodName, nameSpace, params);
        return results;
    }

 需要说明的是,参数的传入,我验证的情况是:
- 顺序必须一致;
- 且参数名必须一致;
 看到的一些博客里讲只需顺序一致即可,我验证不是这样,可以肯定的是,我这样做不会错的。
  第一次访问的webService方法为登陆方法,服务器会返回一个HeaProperty:”set-cookie<—>JsessionId等“,以后每次调用webservice请求都要带上这个cookie,因为这个cookie里带着服务端webservice的session的sessionID,他们的关系很容易理解。可以参考这个博客
  服务器端的代码简单示例:

//登陆
public boolean login(String username, String password) {
        MessageContext mc = MessageContext.getCurrentMessageContext();
        ServiceGroupContext sgc = mc.getServiceGroupContext();
        for(String s:loginaccount){
            String[] itemString = s.split("-");
            System.out.println(username+password);
            System.out.println(itemString[0] + itemString[1]);
            if(username.equals(itemString[0]) && password.equals(itemString[1])) {
                sgc.setProperty("loginState", "成功登录");    
                return true;
            }
        }
        sgc.setProperty("loginState", "登录失败");    
        return false;
    }    
//获取登陆状态    
public String getLoginMsg() {
       //  第1步:获得key-value对中的value
        MessageContext mc = MessageContext.getCurrentMessageContext();
        ServiceGroupContext sgc =  mc.getServiceGroupContext();
        return (String)sgc.getProperty("loginState");
}
//其他方法    
public String otherMethod{
    if(!getLoginMsg().equal("成功登陆"))
      return "error1"
    else
    {
        //做你的业务逻辑
    }
    return "";
}

以上是我最近的一点记录,欢迎讨论,共同进步。

猜你喜欢

转载自blog.csdn.net/xialingming/article/details/81291727