从上一章,我们看到ShineWay背后做了把界面的变化/事件编码成协议的请求包交给后台控制器逻辑进行处理。
并且请求包的格式是XML的,但是我们的XML元素包含的是各式各样的控件的数据,属性等等,如果不作处理,它极有可能把XML格式搞得一塌糊涂。解决这个问题的方法大致有几种:
1.把要嵌入的数据过滤特殊符号,比如<,>等。
2.把数据当作XML的CData部分来传输。
3.把数据完全编码成不可能混淆的部分。
ShineWay选择了第3种方法,原因是,采用第一种方法,我不能保证有多少种情况需要考虑,如果有新的特殊字符需要考虑,我就必须不断更改协议。采用第二种方法,对于XML的解析部分会比较复杂,并且XML文档的可读性不强(可以参考Unix编程艺术中讲到的协议文本化的提议)。
因此,我编写了一段JS来把数据部分编解码为Base64,因为这种编码方式最常用,并且作为XML的数据不会有任何异议(这正好迎合了Unix编程艺术中讲到的最小立异原则),包括EMail最常用的编码方式也是如此,可以增加扩展性的砝码。当然,这种实现算法在互联网上肯定很容易找到其他的版本。
以下是完整代码,作为javascript来说,他实现了一个类EncodeUtils,我们可以这样使用它:
var utils = new EncodeUtils();
utils.EncodeB64(str);
-------------------------------------源码------------------------------------------------
function EncodeUtils(){
this.keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
}
EncodeUtils.create=function(){};
EncodeUtils.prototype.EncodeB64=function(rawStr) {
var escapedStr = encodeURIComponent(rawStr);
var count = 0;
var ints = new Array();
var b64Str = "";
for(var i=0,size=escapedStr.length;i<size;i++){
var ch = escapedStr.charAt(i);
if(ch=='%'){
ints.push(parseInt(escapedStr.charAt(i+1),16)*16+parseInt(escapedStr.charAt(i+2),16));
i += 2;
}else{
ints.push(ch.charCodeAt());
}
if(count++ == 2){
b64Str += this.GetB64Str(ints);
count = 0;
ints.length = 0;
}
}
b64Str += this.GetB64Str(ints);
return b64Str;
};
EncodeUtils.prototype.GetB64Str=function(ints){
if(ints.length==0) return "";
var rawLen = ints.length;
while(ints.length<3){
ints.push(0);
}
var ch1 = this.keyStr.charAt(ints[0] >> 2);
var ch2 = this.keyStr.charAt(((ints[0] & 3) << 4) | (ints[1] >> 4));
var ch3 = this.keyStr.charAt(((ints[1] & 15) << 2) | (ints[2] >> 6));
var ch4 = this.keyStr.charAt(ints[2] & 63);
if(rawLen==1){ch3='=';ch4='=';}
if(rawLen==2){ch4='=';}
return ch1+ch2+ch3+ch4;
};