• [j2me]利用kSOAP让MIDP设备与WebService之间传递类对象[下]


      测试代码下载:https://files.cnblogs.com/zhengyun_ustc/WSCallerMIDlet.rar

    [j2me]利用kSOAPMIDP设备与

    WebService之间传递类对象

    编写者

    日期

    关键词

    郑昀@ultrapower

    2005-8-14

    J2me webservice soa ksoap serialization MIDP CLDC

     

    第二小步,Web Service传递较为复杂的类

    下面我们讲述如何MIDP设备和Web Service之间传递较为复杂的类,比如这个类中不但有String类型成员变量,还有Vector之类的复杂类型

    kSoapFAQ上看,他们推荐使用KvmSerializable以及 ClassMap传递自定义类,但是我一直没有试验成功。

    我还是按照能试验出来的办法讲述一下步骤吧:

    大致思路就是,在服务器端将类实例按照一定规格(一个一个的成员变量写)序列化为byte[],将这个byte[]数组返回给kSOAPkSOAP收到之后反序列化,将byte[]一段一段地读入类实例。

    Web Service服务器端的做法

    先来定义要传递的wsTeam类:

    类定义

    public class wsTeam{

    private String wsReturnCode;

    private String wsPersonCount;

    public StringVector  wsvPersonName;

    public byte[] serialize();

    public static wsTeam deserialize(byte[] data) ;

    }

    其中,StringVector类是另外一个自定义类,就是简单地把String[]封装了一下,便于操作。StringVector类定义在附录中可以找到。

    服务器端主要是序列化,所以我们来讲讲wsTeambyte[] serialize()函数。

    序列化

           public byte[] serialize() {

                  ByteArrayOutputStream baos = new ByteArrayOutputStream();

                  DataOutputStream dos = new DataOutputStream(baos);

     

                  try

                  {

                         dos.writeUTF(wsReturnCode);

                         dos.writeUTF(wsPersonCount);

                         wsvPersonName.writeObject(dos);

                         baos.close();

                         dos.close();

                  }

                  catch(Exception exc)

                  {

                         exc.printStackTrace();

                  }

     

                  return baos.toByteArray();

           }

    这样,类实例就可以把自己序列化为byte[]数组。

    那么,Web Service可以这么提供:

    服务器端

    public class SimpleKSoapWS {

       

        public SimpleKSoapWS () {

        }

       

        public byte[]  foo2(String username, String password) {

            wsTeam obj= new wsTeam ();

               return obj.serialize();

    }

    }

    到了MIDP设备上,要能够从byte[]恢复出wsTeam类实例才行。

     

    StringVector的序列化方法writeObject也很简单,先写入字符串数组的大小,然后再将每一个元素写入,如下所示:

    StringVector的序列化

    public class StringVector

    {…

    public synchronized void writeObject(java.io.DataOutputStream s)

           throws java.io.IOException 

           { 

                  //     Write out array length

                  s.writeInt(count); 

                  //     Write out all elements in the proper order.   

                  for (int i=0; i<count; i++)

                  {

                         s.writeUTF(data[i]);

                  }

           }

    }

     

    MIDP设备的做法

    和前面的MIDlet代码差不多,只不过要我们的ClassMap出场了

    使用ClassMap

    ClassMap classMap = new ClassMap();

    (new MarshalBase64()).register(classMap);

    HttpTransport tx = new HttpTransport(serviceUrl, methodName);

     

    tx.setClassMap( classMap );

    tx.debug = true;

    MarshalBase64类定义在附录中可以找到。

    这样,后面才能将接收到的SoapObject强制转换为byte[]

    转换

    Object Response = tx.call(request);

    System.out.println( tx.responseDump );

    byte[] by = (byte[])Response;

    然后,再调用

    反序列化

    wsTeam wc = wsTeam.deserialize(by);

    这样,在无线设备上就得到了wsTeam类实例了。

     

    wsTeamdeserialize是这么定义的:

    反序列化

    public class StringVector

    {…

           public static wsTeam deserialize(byte[] data) {

                  ByteArrayInputStream bais = new ByteArrayInputStream(data);

                  DataInputStream dis = new DataInputStream(bais);

                  wsTeam wc = new wsTeam();

                 

                  try

                  {

                         wc.wsReturnCode = dis.readUTF();

                         wc.wsPersonCount = dis.readUTF();

                 

                         wc. wsvPersonName.readObject(dis);

          

                         bais.close();

                         dis.close();

                  }

                  catch(Exception exc)

                 

                         exc.printStackTrace();

                  }

     

                  return wc;

           }

    …}

    StringVector的反序列化方法readObject也很简单,先读入字符串数组的大小,就自行新建一个同样大小的字符串数组,然后再将每一个元素写入这个数组,如下所示:

    StringVector的反序列化

    public class StringVector

    {…

           public synchronized void readObject(java.io.DataInputStream s)

           throws java.io.IOException, ClassNotFoundException  

           {    

                  //     Read in array length and allocate array  

                  int arrayLength = s.readInt(); 

                  data = new String[arrayLength]; 

                  // 同步data的大小

                  count = arrayLength;

                  //     Read in all elements in the proper order. 

                  for (int i=0; i<arrayLength; i++)

                  {

                         data[i] = s.readUTF();

                  }

           }…

    }

     

    通过上面的反序列化,我们就可以通过

    for (int i=0; i<wc. wsvPersonName.size(); i++)

    {

          System.out.println("" + i +"个人:" +

                     wc. wsvPersonName.getStringAt(i));

    }

    来打印MIDlet上收到的类对象中的StringVector成员变量了。

     

    小结

    利用相同的办法,您还可以在无线设备和Web Service之间,传递各种各样的类对象,类里面也包含了各种类型的成员变量。

     

    编写者

    日期

    关键词

    郑昀@ultrapower

    2005-8-19

    J2me webservice soa ksoap serialization MIDP CLDC

     

     

    附录AStringVector

    StringVector

    /**

     * Vector主要用来保存各种类型的对象(包括相同类型和不同类型的对象)。

     * 但是在一些情况下使用会给程序带来性能上的影响。这主要是由Vector类的两个特点所决定的。

     * 第一,Vector提供了线程的安全保护功能。即使Vector类中的许多方法同步。

     * 但是如果你已经确认你的应用程序是单线程,这些方法的同步就完全不必要了。

     * 第二,在Vector查找存储的各种对象时,常常要花很多的时间进行类型的匹配。

     * 而当这些对象都是同一类型时,这些匹配就完全不必要了。

     * 因此,有必要设计一个单线程的,保存特定类型对象的类或集合来替代Vector

     */

    package com.ultrapower.helper;

     

    /**

     * @author VictorZheng

     *

     */

    public class StringVector

    {

           // 这儿的transient标示这个属性不需要自动序列化

           private transient String[] data;

           private int count;

           public int size()

           {

                  return count;

           }

           public StringVector()

           {

               // default size is 10

                  this(10);  

           }

           public StringVector(int initialSize)

           {

                  data = new String[initialSize];

           }

           public void add(String str)

           {

                  //     ignore null strings

                  if(str == null) { return; }

                  ensureCapacity(count + 1);

                  data[count++] = str;

           }

     

           private void ensureCapacity(int minCapacity)

           {

                  int oldCapacity = data.length;

                  if (minCapacity > oldCapacity)

                  {

                         String oldData[] = data;

                         int newCapacity = oldCapacity * 2;

                         data = new String[newCapacity];

                         System.arraycopy(oldData, 0, data, 0, count);

                  }

           }

           public void remove(String str)

           {

                  if(str == null)

                  {

                         return; // ignore null str  

                  }

                  for(int i = 0; i < count; i++)

                  {

                         //     check for a match

                         if(data[i].equals(str))

                         {

                                System.arraycopy(data,i+1,data,i,count-1); // copy data

                                //     allow previously valid array element be gc'd

                                data[--count] = null;

                                return;

                         }

                  }

           }

          

           public final String getStringAt(int index)

           {

                  if(index < 0)

                  { return null; }

                  else if(index > count)

                  {

                         return null; // index is > # strings

                  }

                  else

                  {

                         return data[index]; // index is good 

                  }

           }

          

           public synchronized void writeObject(java.io.DataOutputStream s)

           throws java.io.IOException 

           { 

                  //     Write out array length

                  s.writeInt(count); 

                  //     Write out all elements in the proper order.  

                  for (int i=0; i<count; i++)

                  {

                         s.writeUTF(data[i]);

                  }

           }

          

           public synchronized void readObject(java.io.DataInputStream s)

           throws java.io.IOException, ClassNotFoundException  

           {    

                  //     Read in array length and allocate array  

                  int arrayLength = s.readInt(); 

                  data = new String[arrayLength]; 

                  // 同步data的大小

                  count = arrayLength;

                  //     Read in all elements in the proper order. 

                  for (int i=0; i<arrayLength; i++)

                  {

                         data[i] = s.readUTF();

                  }

           }

    }

     

    附录BMarshalBase64

    MarshalBase64

    /**

     * @author VictorZheng

     *

     */

    import java.io.IOException;

     

    import org.kobjects.serialization.ElementType;

    import org.ksoap.ClassMap;

    import org.ksoap.Marshal;

    import org.ksoap.Soap;

    import org.ksoap.SoapParser;

    import org.ksoap.SoapWriter;

     

     

    /** Base64 (de)serializer */

     

     

    public class MarshalBase64 implements Marshal {

     

        static byte [] BA_WORKAROUND = new byte [0];

        public static Class BYTE_ARRAY_CLASS = BA_WORKAROUND.getClass ();  

       

     

        public Object readInstance (SoapParser parser,

                                String namespace, String name,

                                ElementType expected) throws IOException {

     

           parser.parser.read (); // start tag

           Object result = Base64.decode

               (parser.parser.readText ());

           parser.parser.read (); // end tag

           return result;

        }

          

     

        public void writeInstance (SoapWriter writer,

                                Object obj) throws IOException {

     

           writer.writer.write (Base64.encode ((byte[]) obj));

        }

     

        public void register (ClassMap cm) {

           cm.addMapping

               (cm.xsd, "base64Binary",

                MarshalBase64.BYTE_ARRAY_CLASS, this);  

     

           cm.addMapping

               (Soap.ENC, "base64",

                MarshalBase64.BYTE_ARRAY_CLASS, this);

     

        }

    }

     

  • 相关阅读:
    webstrom破解的问题
    redis高级应用(1)
    linux之软链接、硬链接
    爬虫之scrapy、scrapy-redis
    爬虫之xpath、selenuim
    爬虫之Beautifulsoup模块
    爬虫之Reuqests模块使用
    测试项目配置
    Cleary基础
    Redis基础
  • 原文地址:https://www.cnblogs.com/zhengyun_ustc/p/ksoapmidpwebservice2.html
Copyright © 2020-2023  润新知