安卓网络客户端--协议的封装和抽取

协议的封装和抽取这块比较复杂,序列化和反序列化,自己做了一点总结,希望大家多多指点。

一.为什么要进行协议封装

以往的处理方式:利用XmlSerializer一点点编写协议序列化代码

存在问题(假设我们有100个请求需要处理):

1、需要将协议中的请求分配给不同的组员进行处理,也就是大部分组员需要学习协议。

2、学习情况检验,是不是所有的组员都已经很好的理解了协议(开协议研讨会)。

3、进入协议开发阶段,类似的代码需要出现100次,由于不同人员处理,过程中很容易出现错误且抽取工作不统一。

4、开发过程中协议修改了,这就需要所有的组员停下手中工作,更改各自编写的请求代码(开会布置)。

   这种情况下,就会让我们的开发进程减慢,我们的解决办法是,对协议进行封装和抽取。

二.协议封装的几个原则

1.节点对象化

节点对象: Leaf 、 Header

Oelement、Element(请求及回复)、 Body

Message

2.节点序列化

•序列化原则:自己管自己

•序列化范围:只有请求的节点涉及序列化

•序列化顺序:Leaf、Header、Element、Body、Message

•Message节点提供请求入口

•Message节点提供对外的xml文件数据提供方法

3.请求接口(抽象)化

Element接口(抽象)化,所有请求必须实现该接口或继承该抽象类,同时实现定义的获取请求类型标示和请求序列化的方法。以获取当前销售期信息为例说明

4.协议通用化

•协议格式:xml、json

•协议压缩:wbxml (用于将xml文件进行压缩)、二进制流

•新协议制定和已有协议

 

  下面就以一个彩票客户端的选彩协议为例来说明:

信息发送 (查询指定玩法可销售期信息)

发送消息的协议如下:

<?xml version=”1.0” encoding=”utf-8”?>
<message version="1.0">
     <header>              
            <agenterid>889931</agenterid>
            <source>ivr</source>
            <compress>DES</compress>
 
            <messengerid>20091113101533000001</messengerid> 
            <timestamp>20091113101533</timestamp>
            <digest>7ec8582632678032d25866bd4bce114f</digest>

            <transactiontype>12002</transactiontype>
            <username>13200000000</username>
     </header>
     <body>
            <elements>
                  <element>
                         <lotteryid>118</lotteryid>
                         <issues>1</issues>
                  </element>
            </elements> 
     </body>
</message>

 

 

 

三.开始封装,对其中一个叶子节点的序列化.

package cn.piaoye.lottery.protocol;

import org.apache.commons.lang3.StringUtils;
import org.xmlpull.v1.XmlSerializer;

/**
 * 叶子节点
 * 标签名字
 * 值
 * @author piao
 *
 */
public class Leaf {
    private String tagName;
    private String value;
    
    public Leaf(String tagName, String value) {
        super();
        this.tagName = tagName;
        this.value = value;
    }
    
    public Leaf(String tagName) {
        super();
        this.tagName = tagName;
    }

    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    
    //<agenterid>889931</agenterid> 在这里我们要调用序列化方法,把叶子节点给序列化
    /**
     * 序列化叶子
     */
    public void serializer(XmlSerializer serializer){
        try {
            serializer.startTag(null,tagName);
            if(StringUtils.isBlank(value)){
                value="";//屏蔽value为空的情况
            }
            serializer.text(value);
            serializer.endTag(null,tagName);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

四.头信息的封装

 

package cn.piaoye.lottery.protocol;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

import org.apache.commons.codec.digest.DigestUtils;
import org.xmlpull.v1.XmlSerializer;

import cn.piaoye.lottery.ConstantValue;

/**
 * 头信息进行封装
 * @author piao
 *
 */
public class Header {
    //八个叶子
    private Leaf agenterid=new Leaf("agenterid", ConstantValue.AGENTERID);
    private Leaf source=new Leaf("source", ConstantValue.SOURCE);
    private Leaf compress=new Leaf("compress", ConstantValue.COMPRESS);
    
    private Leaf messengerid=new Leaf("messengerid");
    private Leaf timestamp=new Leaf("timestamp");
    private Leaf digest=new Leaf("digest");
    private Leaf transactiontype=new Leaf("transactiontype");
    private Leaf username=new Leaf("username");
    
    /**
     * header部分序列化
     */
    public void serializer(XmlSerializer serializer,String body){
        //第一个叶子节点
        /**
         * messengerid:当前的这个xml的标示
                值:时间戳:yyyyMMddHHmmss   +六位的随机数
                处理方式:SimpleDateFormat    DecimalFormat

         */
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyyMMddHHmmss");
        String time=dateFormat.format(new Date());
        //获取随机数
        Random random=new Random();
        int num=random.nextInt(999999)+1;//1
        //格式化随机数
        DecimalFormat decimalFormat=new DecimalFormat("000000");
        String randomNum = decimalFormat.format(num);
        
        messengerid.setValue(time+randomNum);
        timestamp.setValue(time);
        
        //MD5的摘要信息
        //时间戳+密码+body部分信息。
        String md5Info=time+ConstantValue.AGENTER_PASSWORD+body;
        String md5Hex=DigestUtils.md5Hex(md5Info);
        digest.setValue(md5Hex);
        
        
        try {
            serializer.startTag(null, "header");
            
            //叶子
            agenterid.serializer(serializer);
            source.serializer(serializer);
            compress.serializer(serializer);
            
            messengerid.serializer(serializer);
            timestamp.serializer(serializer);
            digest.serializer(serializer);
            
            transactiontype.serializer(serializer);
            username.serializer(serializer);
            
            serializer.endTag(null, "header");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    //这个我们处理不了,就给他暴露出去
    public Leaf getTransactiontype() {
        return transactiontype;
    }

    public Leaf getUsername() {
        return username;
    }
    
}

 

 

package cn.piaoye.lottery;

public interface ConstantValue {
    String AGENTERID="1000002";//子代理商的标示
    String SOURCE="ivr";//信息来源
    String COMPRESS="DES";//body部分的加密方式
    
    /**
     * 子代理商的密钥
     */
    String AGENTER_PASSWORD = "9ab62a694d8bf6ced1fab6acd48d02f8";
    /**
     * des加密用密钥
     */
    String DES_PASSWORD = "9b2648fcdfbad80f";
}

 

对封装的协议进行测试:

public void testHeader()
    {
        XmlSerializer serializer = Xml.newSerializer();
        try {
            StringWriter writer = new StringWriter();
            serializer.setOutput(writer);
            serializer.startDocument("utf-8", null);

            serializer.startTag(null, "message");
            
            Header header=new Header();
            header.serializer(serializer, "");
            
            // body
            serializer.startTag(null, "body");
            serializer.endTag(null, "body");

            serializer.endTag(null, "message");

            serializer.endDocument();
            Log.i("XmlTest", writer.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }

生成的xml文件为:

<?xml version='1.0' encoding='utf-8'?>
<message> <header>

    <agenterid> 1000002 </agenterid>

    <source>ivr</source>

    <compress> DES </compress>

    <messengerid> 20121224163229736485 </messengerid>

    <timestamp> 20121224163229 </timestamp>

    <digest> a6bcb107c326f21006233dd67d9fc038 </digest>

    <transactiontype> </transactiontype>

    <username> </username>
</header>

<body />

</message>
posted @ 2012-12-24 16:48  Andye  阅读(2557)  评论(2编辑  收藏  举报