安卓網絡客戶端--協議的封裝和抽取


協議的封裝和抽取這塊比較復雜,序列化和反序列化,自己做了一點總結,希望大家多多指點。

一.為什么要進行協議封裝

以往的處理方式:利用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>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM