`

让Ajax框架Buffalo支持JSON协议而非仅仅自定义的XML协议[JS前端及单元测试完成]

阅读更多

Buffalo默认实现了一套很棒的自定义XML协议(具体请参考拙作《Ajax框架Buffalo深度研究》)。

然而在崇尚“标准”的当下,很多人对这种“非标准”的自定义的协议并不感冒,哪怕它再好。

在这种情况下,本人也是本着对Buffalo的继续研究、提升自我的态度,尝试基于org.json的“正宗”JSON参考实现RI,让Buffalo完全支持JSON标准协议。

 

本来打算自己默默研究,等完全成型之后再发布出来,然而自《Ajax框架Buffalo深度研究》发布后,在社区所凝聚的人气之旺,让我有些震惊(或者说惊喜),继而灵机一动:何不利用社区的强大平台,在线开展此项工作呢?

不能保证每天甚至每周都有让人惊喜的进展,仅希望通过这种方式,鞭策自己的同时,也获得更多社区高手的批评斧正,快速提升,少走弯路。

 

接下来的工作,欢迎各位踊跃拍砖,谢谢!

 

 

2010-02-08,状态简述:

1)前端js已经编写完成:充分结合XML协议和JSON协议,完成了代码的重构

2)单元测试已经完成,并提供了完整的参考XML协议的js单一测试用例(同样基于script.aculo.us 的unittest.js)

3)升级prototype.js到最新的1.6.1(其实buffalo对prototype.js依赖不大)

接下来的工作:

1、完成前后端集成测试,并完善demo

2、适时开展RC

 

2010-01-25,状态简述:

1)后端代码重构完成,并已纳入buffalo SVN, 建立了新的branch,位于branches/json/;

2)接下来工作的重点是:a.着手编写前台js; c.并结合demo完成集成测试。

分享到:
评论
27 楼 itstarting 2010-03-10  
<p>Bug-fixed:net.buffalo.protocal.BuffaloProtocal.java</p>
<p> </p>
<p>原先也提到取得BuffaloProtocal单例的时候会产生线程安全问题,其实能看的出来,为了慎重起见,还特意写了测试代码验证并得到确认。</p>
<p> </p>
<p>最后进行了修复:</p>
<p> </p>
<pre name="code" class="java">……
private static Map instanceMap = new HashMap();

……

public static BuffaloProtocal getInstance(String p){
BuffaloProtocal instance = (BuffaloProtocal) instanceMap.get(p);
if (instance == null) {
instance = new BuffaloProtocal();
instance.protocol = p;
instanceMap.put(p, instance);
}
return instance;
}</pre>
<p> </p>
<p> </p>
<p>其实也很简单,用了一个Map,对XML和JSON各放了一个实例。</p>
<p> </p>
26 楼 itstarting 2010-02-08  
<h2 style="margin: 12pt 0cm; text-indent: 0cm;">
<span style=""><span style=""><span style='font-family: "Times New Roman";'> </span></span></span><span style="font-size: large;"><span style="">前端</span><span lang="EN-US"><span style="font-family: Times New Roman;">JS</span></span></span>
</h2>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">其实服务端的重构是前段时间的事,也放到了SVN的分支(buffalo/branches/json)上了</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">近期杂事太多,耽搁了一下,但终于还是回到了前端。</span></span></p>
<p><span style="">
<h3 style="margin: 12pt 0cm; text-indent: 0cm;"><span style=""><span style="font-size: large;">说在开发前端前的话</span></span></h3>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">老实说,我的前端架构、设计和开发能力要打折扣,但还是要硬着头皮上。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">同样前端还是采用了</span><span lang="EN-US"><span style="font-family: Times New Roman;">TDD</span></span><span style="">,基于</span><span lang="EN-US"><span style="font-family: Times New Roman;">script.aculo.us</span></span><span style="">所提供的</span><span lang="EN-US"><span style="font-family: Times New Roman;">unittest.js</span></span><span style="">做,还真的不错,不过实话说,咱还没干过</span><span lang="EN-US"><span style="font-family: Times New Roman;">js TDD</span></span><span style="">,顺道学一把。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">重点说说目标:</span></span></p>
<p class="MsoNormal" style=""><span style="" lang="EN-US"><span style=""><span style="font-family: Times New Roman;"><span style="font-size: small;">1、</span><span style='font-family: "Times New Roman";'>  </span></span></span></span><span style="font-size: small;"><span style="">平滑的实现兼容</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">协议的客户端;</span></span></p>
<p class="MsoNormal" style=""><span style="" lang="EN-US"><span style=""><span style="font-family: Times New Roman;"><span style="font-size: small;">2、</span><span style='font-family: "Times New Roman";'>  </span></span></span></span><span style=""><span style="font-size: small;">重构客户端脚本。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<h3 style="margin: 12pt 0cm; text-indent: 0cm;"><span style=""><span style="font-size: large;">开发的重点</span></span></h3>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">要说重点,主要还是一去一回:协议的封装和返回的解析。</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p><span style="">
<h4 style="margin: 12pt 0cm; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small; font-family: Times New Roman;">call.js</span></span></h4>
</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="" lang="EN-US">call</span><span style="">我的思路是:对外提供一致的接口,用类似于</span><span style="" lang="EN-US">Factory</span><span style="">模式的机制来做具体实现的生产和封装——</span><span style="" lang="EN-US">js</span><span style="">的</span><span style="" lang="EN-US">OOP</span><span style="">其实也是不错的,但我不是太会用,将就着先出一个</span><span style="" lang="EN-US">beta</span><span style="">版吧。</span></span></p>
<font style="">
<p> </p>
</font></span></p>
<p> </p>
<pre name="code" class="js">Buffalo.Call = Class.create();
Buffalo.Call.prototype = {
initialize: function(methodname,protocol){
this.method = methodname;
this.params = [];
this.protocol = (protocol!=null &amp;&amp; (protocol=='XML' || protocol=='JSON'))
? protocol
: Buffalo.DefaultProtocol;
},

addParameter: function(data){
if (typeof(data) == 'undefined') return;
this.params[this.params.length] = data;
},

toCall: function(){
return (this.protocol == 'JSON')
? this._json()
: this._xml();
},

_xml: function(){
var s = "&lt;buffalo-call&gt;\n";
s += "&lt;method&gt;" + this.method+ "&lt;/method&gt;\n";
for (var i = 0; i &lt; this.params.length; i++) {
  var data = this.params[i];
  var p = new Buffalo.XML(this, data);
  s += p.parseValue(data) + "\n";
}
s += "&lt;/buffalo-call&gt;";
return s;
},

_json: function(){
//demo:[{'buffalo-call':[{'method':'divide'},{'double':1},{'double':2}]]
var s = "[{'buffalo-call':[\n";
s += "{'method':'" + this.method+ "'}\n";
for (var i = 0; i &lt; this.params.length; i++) {
  var data = this.params[i];
  var p = new Buffalo.JSON(this, data);
  s += p.parseValue(data) + "\n";
}
s += "]";
return s;
},

getProtocol : function() {
return this.protocol;
}
}
</pre>
<p> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">把原先在这里面的一些方法一分为二:一部分变成了具体的</span><span lang="EN-US"><span style="font-family: Times New Roman;">XML</span></span><span style="">实现,一部分新建了一个</span><span lang="EN-US"><span style="font-family: Times New Roman;">Utils</span></span><span style="">的</span><span lang="EN-US"><span style="font-family: Times New Roman;">Class</span></span><span style="">。这些就略了,有兴趣自己</span><span lang="EN-US"><span style="font-family: Times New Roman;">down</span></span><span style="">下来看。</span></span></p>
<p> </p>
<h4 style="margin: 12pt 0cm; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small; font-family: Times New Roman;">json.js</span></span></h4>
<p> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">下面是</span><span lang="EN-US"><span style="font-family: Times New Roman;">json.js</span></span><span style="">的实现:</span></span></p>
<p><span style="font-size: small;">
<p><span style="">
<pre name="code" class="js">/** JSON Implementation */
Buffalo.JSON = Class.create();
Buffalo.JSON.prototype = {
initialize : function(call, data) {
this.call = call;
this.data = data;
    this._objects = [];
},

parseValue : function(data) {
var s;
var type = Buffalo.Utils.typeOfData(data);
switch (type) {
case "date":
s = this.doDate(data);
break;
case "list":
s = this.doArray(data);
break;
case "map":
s = this.doStruct(data);
break;
case "boolean":
s = this.doBoolean(data);
break;
case "null":
s = this.doNull();
break;
default:
s = this.doValue(type, data);
break;
}
return s;
},

doDate : function(data) {
var s = "{'date':'";
s += Buffalo.Utils.dateToISO8609(data);
s += "'}";
return "," + s;
},

doValue : function(type, data) {
var s;
if (typeof (data) == "string") {
data = data.replace(/&amp;/g, "&amp;amp;");
data = data.replace(/&lt;/g, "&amp;lt;");
data = data.replace(/&gt;/g, "&amp;gt;");
data = data.replace(/'/g, "/'");
}
s = "{'" + type + "':'" + data + "'}";

return "," + s;
},

doBoolean : function(data) {
var value = (data == true) ? 1 : 0;
var s = "{'boolean':" + value + "}";
return "," + s;
},

doArray : function(data) {
var ref = this._checkRef(data);
if (ref != -1) return "{'ref':" + ref + "}";
this._objects[this._objects.length] = data;

var s = "{'list':[\n";
var boClass = data[Buffalo.BOCLASS];
var boType = boClass ? boClass : Buffalo.Utils.typeOfArray(data);
s += "{'type':'" + boType + "'}\n";
s += ",{'length':" + data.length + "}\n";
for ( var i = 0; i &lt; data.length; i++) {
s += this.parseValue(data[i]) + "\n";
}
s += "]}\n";
return "," + s;
},

doStruct : function(data) {
var ref = this._checkRef(data);
if (ref != -1)
return "{'ref':" + ref + "}";
this._objects[this._objects.length] = data;

var boType = data[Buffalo.BOCLASS] || "java.util.HashMap";
var s = "{'map':[\n";
s += "{'type':'" + boType + "'}\n";

for ( var i in data) {
if (data[i] != boType) {
if (typeof (data[i]) == "function")
continue; /* the function shouldn't transfered. */
s += this.parseValue(i) + "\n";
s += this.parseValue(data[i]) + "\n";
}
}
s += "]}\n";
return "," + s;
},

doNull : function() {
return "," + "{'null':null}";
},




_checkRef : function(obj) {
var ref = -1;
for ( var i = 0; i &lt; this._objects.length; i++) {
if (obj === this._objects[i]) {
ref = i;
break;
}
}
return ref;
}
};
</pre>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
</span></p>
</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<pre name="code" class="js">Buffalo.Reply = Class.create();
Buffalo.Reply.prototype = {
initialize: function(xhr,protocol) {
this._isFault = false;
this._type = "null";
this._source = xhr.responseText;
this._impl = (protocol == 'JSON')
? new Buffalo.Reply.JSON(xhr, this._source)
: new Buffalo.Reply.XML(xhr, this._source);
},

/** interface : getType, get the response object type */
getType: function() { return this._impl.getType(); },

/** interface : getResult, deserialize the response and return the javascript object */
getResult : function() { return this._impl.getResult(); },

/** interface : isFault, check response is fault or not */
isFault : function() { return this._impl.isFault(); },

/** interface : isFault, check response is null or not */
isNull: function() { return this._impl.isNull(); },

getSource : function() { return this._source; },
}
</pre>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">然后分别实现。后面的代码很多,就不贴了。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">说实话,</span><span lang="EN-US"><span style="font-family: Times New Roman;">js</span></span><span style="">的</span><span lang="EN-US"><span style="font-family: Times New Roman;">OOD/OOP</span></span><span style="">也蛮有意思的,但一时半会儿还不顺手。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;">
</p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;">
</p>
<p>
</p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>


25 楼 itstarting 2010-02-07  
<h2 style="margin: 12pt 0cm; text-indent: 0cm;"><span style=""><span style="font-size: large;">服务端的重构</span></span></h2>
<p> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">考虑到在纳入</span><span lang="EN-US"><span style="font-family: Times New Roman;">SVN</span></span><span style="">前完成重构,挤出点时间完成了重构。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">所谓的重构,其实很简单,就是新增了两个抽象类方法,采用</span><span lang="EN-US"><span style="font-family: Times New Roman;">Template</span></span><span style="">模式进行了抽象与具体的分离。</span></span></p>
<p class="MsoNormal" style=""><span style="font-family: Times New Roman;"><span style="" lang="EN-US"><span style=""><span style="font-size: small;">1、</span><span style='font: 7pt "Times New Roman";'>  </span></span></span><span lang="EN-US"><span style="font-size: small;">AbstractStreamReader.java</span></span></span></p>
<p class="MsoNormal" style=""><span style="font-family: Times New Roman;"><span style="" lang="EN-US"><span style=""><span style="font-size: small;">2、</span><span style='font: 7pt "Times New Roman";'>  </span></span></span><span lang="EN-US"><span style="font-size: small;">AbstractStreamWriter.java</span></span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">这样,无论是</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">还是</span><span lang="EN-US"><span style="font-family: Times New Roman;">XML</span></span><span style="">的</span><span lang="EN-US"><span style="font-family: Times New Roman;">IO</span></span><span style="">实现,都变成了很简单,也更聚焦了。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">类图如下:</span></span></p>
<p><br><img src="http://dl.iteye.com/upload/attachment/204423/70a9f5c8-9036-37df-be7c-43e9584d665a.gif" alt=""><br> <br><img src="http://dl.iteye.com/upload/attachment/204425/14a4ceff-46f3-3534-bcd1-dc76472009b2.gif" alt=""><br> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">OK</span></span><span style="">,很简单的套路,但显然,具体协议实现代码变得非常的简单,可读性大大增加了。以后再出现什么阿猫阿狗协议,只要好的,你都可以遵照实现,难度大大降低咯。</span></span></p>
24 楼 itstarting 2010-01-21  
为了发布上面的这个回复,我老老实实的提交-》不行(都是缺胳膊少腿的)-》编辑了足足5遍!!

Robbin TX啊,这么牛气哄哄(回帖还需要考试)的网站,可不能被这个破编辑器给砸了呀
23 楼 itstarting 2010-01-21  
<p><span><span style="font-size: small;"><span lang="EN-US"><strong>net.buffalo.protocal.io.json.JsonStreamWriter</strong></span></span></span></p>
<p><span><span style="font-size: small;"><span lang="EN-US"><strong></strong></span></span></span></p>
<p><span><span style="font-size: small;"><span lang="EN-US">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">接下来就干这个了。</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">这个相对而言容易些,加上写</span><span lang="EN-US"><span style="font-family: Times New Roman;">JsonStreamWriter</span></span><span style="">的经验,自然顺当些了。</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">原先提供的测试用例明显不足,也顺便完善了这块。</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">总体而言,花了个把小时开发和调试,整体就比较完善了,测试用例的思考和编写,反倒花费了更多的心思。</span></p>
<h4 style="margin: 12pt 0cm; text-indent: 0cm;">
<span style="" lang="EN-US"><span style=""><span style='font: 7pt "Times New Roman";'>  </span></span></span><span style="">核心方法</span>
</h4>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span lang="EN-US"><span style="font-family: Times New Roman;">startNode</span></span><span style="">:</span></p>
<p>
</p>
<table class="MsoTableGrid" style="border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0"><tbody><tr style="">
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; background-color: transparent;" width="568" valign="top">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">    </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">public</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> </span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">void</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> startNode(String name) {<span style="">      </span></span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">if</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">(</span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">isStart</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">){</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">           </span></span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">writer</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">.write(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"["</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">           </span></span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">stack</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">.push(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"["</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span>}</span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">else</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> </span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">if</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">(</span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">depth</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">&gt;0){</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">           </span></span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">writer</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">.write(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">","</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span>}</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">writer</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">.write(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"{'"</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">writer</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">.write(name);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">writer</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">.write(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"':"</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">stack</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">.push(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"{"</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">depth</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">++;</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">isStart</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> = </span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">true</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">;</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style='font-size: 10pt; color: black; line-height: 120%; font-family: "Courier New";' lang="EN-US"><span style="">    </span>}</span></p>
</td>
</tr></tbody></table></span></span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span lang="EN-US"><span style="font-family: Times New Roman;">endNode</span></span><span style="">:</span></p>
<p>
</p>
<table class="MsoTableGrid" style="border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0"><tbody><tr style="">
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; background-color: transparent;" width="568" valign="top">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">    </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">public</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> </span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">void</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> <span style="background: silver;">endNode</span>() {</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">depth</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">--;</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span>String beginFlag = (String) </span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">stack</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">.pop();</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">if</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">(beginFlag.equals(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"["</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">)) write(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"]"</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">if</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">(beginFlag.equals(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"{"</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">)) write(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"}"</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">if</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">(</span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">depth</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> == 0) {</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">           </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">while</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">(</span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">stack</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">.hasStuff()){</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">              </span>beginFlag = (String) </span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">stack</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">.pop();</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">              </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">if</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">(beginFlag.equals(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"["</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">)) write(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"]"</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">              </span></span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">if</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">(beginFlag.equals(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"{"</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">)) write(</span><span style='font-size: 10pt; color: #2a00ff; font-family: "Courier New";' lang="EN-US">"}"</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">);</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">           </span>}<span style="">          </span></span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">           </span>flush();</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span>}</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 0cm; line-height: normal; text-align: left;" align="left"><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"><span style="">       </span></span><span style='font-size: 10pt; color: #0000c0; font-family: "Courier New";' lang="EN-US">isStart</span><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US"> = </span><strong><span style='font-size: 10pt; color: #7f0055; font-family: "Courier New";' lang="EN-US">false</span></strong><span style='font-size: 10pt; color: black; font-family: "Courier New";' lang="EN-US">;</span><span style='font-size: 10pt; font-family: "Courier New";' lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style='font-size: 10pt; color: black; line-height: 120%; font-family: "Courier New";' lang="EN-US"><span style="">    </span>}</span></p>
</td>
</tr></tbody></table>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span lang="EN-US"><span style="font-family: Times New Roman;"> </span></span></p>
<h4 style="margin: 12pt 0cm; text-indent: 0cm;"><span style="">测试用例</span></h4>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">提供更为丰富的测试用例:</span></p>
<p>
</p>
<table class="MsoTableGrid" style="margin: auto 6.75pt; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0" align="left"><tbody>
<tr style="">
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 4cm; padding-top: 0cm; background-color: transparent;" width="151" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm; text-align: center;" align="center"><strong style=""><span style="font-size: small;"><span style="">测试用例</span><span lang="EN-US"></span></span></strong></p>
</td>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 312.7pt; padding-top: 0cm; background-color: transparent;" width="417" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm; text-align: center;" align="center"><strong style=""><span style="font-size: small;"><span style="">说明</span><span lang="EN-US"></span></span></strong></p>
</td>
</tr>
<tr style="">
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; width: 4cm; padding-top: 0cm; background-color: transparent;" width="151" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small; font-family: Times New Roman;">testPrimitive</span></span></p>
</td>
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 312.7pt; padding-top: 0cm; background-color: transparent;" width="417" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style="font-size: small;"><span style="">测试</span><span lang="EN-US"><span style="font-family: Times New Roman;">"boolean","date","double","double","long","string","null","node"</span></span><span style="">等基本对象</span></span></p>
</td>
</tr>
<tr style="">
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; width: 4cm; padding-top: 0cm; background-color: transparent;" width="151" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small; font-family: Times New Roman;">testNested</span></span></p>
</td>
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 312.7pt; padding-top: 0cm; background-color: transparent;" width="417" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style=""><span style="font-size: small;">测试存在基本嵌套的对象</span></span></p>
</td>
</tr>
<tr style="">
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; width: 4cm; padding-top: 0cm; background-color: transparent;" width="151" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small; font-family: Times New Roman;">testList</span></span></p>
</td>
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 312.7pt; padding-top: 0cm; background-color: transparent;" width="417" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style=""><span style="font-size: small;">测试列表对象</span></span></p>
</td>
</tr>
<tr style="">
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; width: 4cm; padding-top: 0cm; background-color: transparent;" width="151" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small; font-family: Times New Roman;">testMap</span></span></p>
</td>
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 312.7pt; padding-top: 0cm; background-color: transparent;" width="417" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style="font-size: small;"><span style="">测试</span><span lang="EN-US"><span style="font-family: Times New Roman;">map</span></span><span style="">对象</span></span></p>
</td>
</tr>
<tr style="">
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; width: 4cm; padding-top: 0cm; background-color: transparent;" width="151" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small; font-family: Times New Roman;">testfault</span></span></p>
</td>
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 312.7pt; padding-top: 0cm; background-color: transparent;" width="417" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style=""><span style="font-size: small;">测试异常对象</span></span></p>
</td>
</tr>
<tr style="">
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; width: 4cm; padding-top: 0cm; background-color: transparent;" width="151" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small; font-family: Times New Roman;">testComplex</span></span></p>
</td>
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 312.7pt; padding-top: 0cm; background-color: transparent;" width="417" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style="font-size: small;"><span style="">测试最为复杂的多重嵌套对象。</span><span lang="EN-US"><span style="font-family: Times New Roman;">List-&gt;Map-&gt;List</span></span></span></p>
</td>
</tr>
</tbody></table>
<p> </p>

<p> </p>
22 楼 itstarting 2010-01-21  
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">经过两天的努力,终于攻克了各种难关,成功实现了所有测试用例的验证,核心方法如下:</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">moveDown</span></span><span style="">:</span></span></p>
<pre name="code" class="java"> public void moveDown() {
int tag = parseTag();
switch(tag) {
case TAG_METHOD:
case TAG_INT:
case TAG_LENGTH:
case TAG_TYPE:
case TAG_STRING:
case TAG_BOOLEAN:
case TAG_LONG:
case TAG_DATE:
case TAG_DOUBLE:
case TAG_NULL:
case TAG_REF:
case TAG_LIST:
case TAG_MAP:
case TAG_CALL:
currentTag = new Tag(tag, parseString());
stack.push(currentTag);
depth++;
break;

default: throw new ProtocolException("unexpected tag: " + tagName(tag));
}
}
</pre>
<p> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span lang="EN-US"><span style="font-size: small; font-family: Times New Roman;">moveUp:</span></span></p>
<p><span lang="EN-US"></span></p>
<pre name="code" class="java"> public void moveUp() {
int ch = skipWhitespace();
if (ch == '}'){
depth--;
stack.pop();
currentTag = (Tag) stack.get(depth-1);
}else if(ch == ']'){
depth--;
stack.pop();
currentTag = (Tag) stack.get(depth-1);
ch = skipWhitespace();
if (ch != '}') throw expectedChar("'}'", ch);
}else throw expectedChar("'}' or ']'", ch);
}
</pre>
<p> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 20pt;"><span style="font-size: 10pt; color: #000000; line-height: 120%; font-family: 'Courier New';">parseTag:</span></p>
<p><span style="font-size: 10pt; color: #000000; line-height: 120%; font-family: 'Courier New';">
<pre name="code" class="java"> protected int parseTag() {
int ch = skipWhitespace();

if(ch == '[') {
ch = skipWhitespace();
}else if (ch == ',') {
ch = skipWhitespace();
}else throw expectedChar("'[' or ','", ch);

int endChar;
if (ch != '{') throw expectedChar("'{'", ch);
ch = read();
if (ch != '\'' &amp;&amp; ch != '"') throw expectedChar("'\'' or '\"'", ch);
endChar = ch;
ch = read();

if (!isTagChar(ch)) throw expectedChar("tag", ch);
sbuf.setLength(0);
for (; isTagChar(ch); ch = read()) sbuf.append((char) ch);
if (ch != endChar) throw expectedChar("'"+endChar+"'", ch);
Integer value = (Integer) tagCache.get(sbuf.toString());
if (value == null) throw new ProtocolException("Unknown tag '" + sbuf + "'");

return value.intValue();
}
</pre>
<p> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 20pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span lang="EN-US"><span style="font-size: small; font-family: Times New Roman;">parseString:</span></span></p>
<p>
</p>
<pre name="code" class="java"> protected String parseString() {
sbuf.setLength(0);
int ch = readChar();
if (ch != ':') throw expectedChar("':'", ch);
int endChar = -1;
ch = readChar();
if (ch == '\'' || ch == '"'){
endChar = ch;
ch = readChar();
}else if (ch == '[') {
peekChar = ch;
return "[";
}
if(ch == endChar) return "";
sbuf.append((char) ch);
while ((ch = readChar()) &gt;= 0) sbuf.append((char) ch);
if(endChar&gt;0 &amp;&amp; sbuf.charAt(sbuf.length()-1) == endChar){
return sbuf.substring(0, sbuf.length()-1);
}else{
return sbuf.toString();
}
}
</pre>
<p> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<h4 style="margin: 12pt 0cm; text-indent: 0cm;">
<span style=""><span style=""><span style="font-family: 'Times New Roman';"> </span></span></span><span style=""><span style="font-size: small;">测试用例</span></span>
</h4>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">所提供的测试用例包括标准的</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo-call</span></span><span style="">请求,以及其他通用的</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">格式,均能有效解析。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">所提供的测试用例清单如下:</span></span></p>
<p><span style=""><span style="font-size: small;">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;">
</p>
<table class="MsoTableGrid" style="margin: auto 6.75pt; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0" align="left"><tbody>
<tr style="">
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 149.4pt; padding-top: 0cm; background-color: transparent;" width="199" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm; text-align: center;" align="center"><strong style=""><span style="font-size: small;"><span style="">测试用例</span><span lang="EN-US"></span></span></strong></p>
</td>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 276.7pt; padding-top: 0cm; background-color: transparent;" width="369" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm; text-align: center;" align="center"><strong style=""><span style="font-size: small;"><span style="">说明</span><span lang="EN-US"></span></span></strong></p>
</td>
</tr>
<tr style="">
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; width: 149.4pt; padding-top: 0cm; background-color: transparent;" width="199" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small;"><span style="font-family: Times New Roman;">testSimpleCall</span></span></span></p>
</td>
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 276.7pt; padding-top: 0cm; background-color: transparent;" width="369" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style="font-size: small;"><span style="">简单的</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo-call</span></span></span></p>
</td>
</tr>
<tr style="">
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; width: 149.4pt; padding-top: 0cm; background-color: transparent;" width="199" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small;"><span style="font-family: Times New Roman;">testCallWithMap</span></span></span></p>
</td>
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 276.7pt; padding-top: 0cm; background-color: transparent;" width="369" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style="font-size: small;"><span style="">带</span><span lang="EN-US"><span style="font-family: Times New Roman;">map</span></span><span style="">的相对复杂的</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo-call</span></span></span></p>
</td>
</tr>
<tr style="">
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; width: 149.4pt; padding-top: 0cm; background-color: transparent;" width="199" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small;"><span style="font-family: Times New Roman;">testHasMoreChildren</span></span></span></p>
</td>
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 276.7pt; padding-top: 0cm; background-color: transparent;" width="369" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style="font-size: small;"><span style="">复杂的用以测试</span><span lang="EN-US"><span style="font-family: Times New Roman;">hasMoreChildren</span></span><span style="">方法的</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo-call</span></span></span></p>
</td>
</tr>
<tr style="">
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; width: 149.4pt; padding-top: 0cm; background-color: transparent;" width="199" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small;"><span style="font-family: Times New Roman;">testComplexTest</span></span></span></p>
</td>
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 276.7pt; padding-top: 0cm; background-color: transparent;" width="369" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style="font-size: small;"><span style="">最复杂的混杂</span><span lang="EN-US"><span style="font-family: Times New Roman;">map/list/primitive</span></span><span style="">的</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo-call</span></span></span></p>
</td>
</tr>
<tr style="">
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; width: 149.4pt; padding-top: 0cm; background-color: transparent;" width="199" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small;"><span style="font-family: Times New Roman;">testPrimitive</span></span></span></p>
</td>
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 276.7pt; padding-top: 0cm; background-color: transparent;" width="369" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style="font-size: small;"><span style="">非</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo-call</span></span><span style="">的标准的</span><span lang="EN-US"><span style="font-family: Times New Roman;">primitive</span></span><span style="">格式的</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span></span></p>
</td>
</tr>
<tr style="">
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; width: 149.4pt; padding-top: 0cm; background-color: transparent;" width="199" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small;"><span style="font-family: Times New Roman;">testNull</span></span></span></p>
</td>
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 276.7pt; padding-top: 0cm; background-color: transparent;" width="369" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style="font-size: small;"><span style="">非</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo-call</span></span><span style="">的标准的</span><span lang="EN-US"><span style="font-family: Times New Roman;">null</span></span><span style="">格式的</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span></span></p>
</td>
</tr>
<tr style="">
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; width: 149.4pt; padding-top: 0cm; background-color: transparent;" width="199" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small;"><span style="font-family: Times New Roman;">testList</span></span></span></p>
</td>
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 276.7pt; padding-top: 0cm; background-color: transparent;" width="369" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style="font-size: small;"><span style="">非</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo-call</span></span><span style="">的标准的</span><span lang="EN-US"><span style="font-family: Times New Roman;">list</span></span><span style="">格式的</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span></span></p>
</td>
</tr>
<tr style="">
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; width: 149.4pt; padding-top: 0cm; background-color: transparent;" width="199" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: small;"><span style="font-family: Times New Roman;">testChineseChar</span></span></span></p>
</td>
<td style="padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: #ece9d8; width: 276.7pt; padding-top: 0cm; background-color: transparent;" width="369" valign="top">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 0cm;"><span style="font-size: small;"><span style="">非</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo-call</span></span><span style="">的标准的带中文字符的</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span></span></p>
</td>
</tr>
</tbody></table></span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<span style=""><font size="3">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
</font></span></span>
</p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<span style=""></span>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">抱怨一下:javaeye的编辑器一旦带有代码,往往需要反复编辑多次才能成功,否则会被莫名其妙的截掉了,我不得不把所有注释都干掉了——也该改进了!</span></span></p>

21 楼 itstarting 2010-01-21  
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">我想到了</span><span lang="EN-US"><span style="font-family: Times New Roman;">’[‘</span></span><span style="">字符。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">经过努力,以下测试用例通过了:</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">:</span></span></p>
<p><span style="font-size: small;"><span style="">
<pre name="code" class="java">private String callWithMap = "[{'buffalo-call':''},{'method':'sum'}," +
                                "{'int':1}," +
"{'map':[{'type':java.util.HashMap},{'string':'key1'},{'string':'value1'},{'string':'key2'},{'string':'value2'}]}," +
"{'string':test}" +
"]";
</pre>
<p><span style=""></span></p>
<p><span style=""><span style="">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">测试用例代码:</span></p>
</span></span>
</p>
<p><span style="">
<pre name="code" class="java"> // callWithMap - PASS
public void testShoudReadNested() throws Exception {
StringReader reader = new StringReader(callWithMap);
StreamReader streamReader = new JsonStreamReader(reader);
assertEquals("buffalo-call", streamReader.getNodeName());
streamReader.moveDown();
assertEquals("method", streamReader.getNodeName());
assertEquals("sum", streamReader.getValue());
streamReader.moveUp();
streamReader.moveDown();
assertEquals("int", streamReader.getNodeName());
assertEquals("1", streamReader.getValue());

streamReader.moveUp();
streamReader.moveDown();
assertEquals("map", streamReader.getNodeName());
streamReader.moveDown();
assertEquals("type", streamReader.getNodeName());
assertEquals("java.util.HashMap", streamReader.getValue());
streamReader.moveUp();
streamReader.moveDown();
assertEquals("string", streamReader.getNodeName());
assertEquals("key1", streamReader.getValue());
streamReader.moveUp();
streamReader.moveDown();
assertEquals("string", streamReader.getNodeName());
assertEquals("value1", streamReader.getValue());
streamReader.moveUp();
streamReader.moveDown();
assertEquals("string", streamReader.getNodeName());
assertEquals("key2", streamReader.getValue());
streamReader.moveUp();
streamReader.moveDown();
assertEquals("string", streamReader.getNodeName());
assertEquals("value2", streamReader.getValue());
streamReader.moveUp();

streamReader.moveUp();
streamReader.moveDown();
assertEquals("string", streamReader.getNodeName());
assertEquals("test", streamReader.getValue());

streamReader.moveUp();
}
</pre>
</span>
</p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">到了测试</span><span lang="EN-US"><span style="font-family: Times New Roman;">hasMoreChildren</span></span><span style="">的时候,正如</span><span lang="EN-US"><span style="font-family: Times New Roman;">JsonStandardStreamReader</span></span><span style="">编写过程中所遇到的困难一样,困难又来了。</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">如何处理好层级关系,理顺</span><span lang="EN-US"><span style="font-family: Times New Roman;">’[‘</span></span><span style="">和</span><span lang="EN-US"><span style="font-family: Times New Roman;">’]’</span></span><span style="">字符的关系是重点。</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">重新审视了</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">表达式,决定再一次改版,如下:</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span lang="EN-US"><span style="font-family: Times New Roman;">simpleCall</span></span><span style="">:</span></p>
<p><span style="">
<pre name="code" class="java">[{'buffalo-call':[{'method':'divide'},{'double':1},{'double':2}]]</pre>
</span>
</p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span lang="EN-US"><span style="font-family: Times New Roman;">callWithMap</span></span><span style="">:</span></p>
<p><span style="">
<pre name="code" class="java">[{'buffalo-call':[{'method':'sum'},{'int':1},{'map':[{'type':java.util.HashMap},{'string':'key1'},{'string':'value1'},{'string':'key2'},{'string':'value2'}]},{'string':test}]]</pre>
</span>
</p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span lang="EN-US"><span style="font-family: Times New Roman;">hasMoreChildren</span></span><span style="">:</span></p>
<p><span style="">
<pre name="code" class="java">[{'buffalo-call':[{'method':'sum'},{'int':1},{'map':[{'type':java.util.HashMap},{'string':'key1'},{'string':'value1'},{'string':'list1'},{'list':[{'type':'java.util.ArrayList'},{'length':3},{'string':a},{'int':2},{'double':8.88}]},]}]]</pre>
</span>
</p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">简洁多了吧,主要还是考虑</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">的层级关系,通过层级开始字符</span><span lang="EN-US"><span style="font-family: Times New Roman;">’[‘</span></span><span style="">和层级关闭字符</span><span lang="EN-US"><span style="font-family: Times New Roman;">’]’</span></span><span style="">,应该可以更好的处理</span><span lang="EN-US"><span style="font-family: Times New Roman;">hasMoreChildren</span></span><span style="">接口。</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">还好,这样改动后对</span><span lang="EN-US"><span style="font-family: Times New Roman;">simpleCall</span></span><span style="">和</span><span lang="EN-US"><span style="font-family: Times New Roman;">callWithMap</span></span><span style="">测试用例没有任何影响,</span><span lang="EN-US"><span style="font-family: Times New Roman;">PASS</span></span><span style="">。</span></p>
<span style="">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<span style=""><span style="">
<p> </p>
<font size="3"><font style="">
<p> </p>
</font>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
</font></span>
<p> </p>
</span></span></span></span></p>




<font size="3">
<p>
</p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>

</font>
<p>
</p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>

<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
20 楼 itstarting 2010-01-19  
老实说,也不是没在JSON的表达样式上思考过,我在写测试用例时就推翻了不下两个版本

我现在初步的考虑是:先完成一个解析JSON的版本的解析器,通过不同call请求对不同协议的需求,无缝的实现XML和JSON的输入-》解析-》服务寻址-》调用-》解析-》输出的同样过程。

也就是说,我要求自己写的JSON实现,在相同的测试用例下要一摸一样,同时都能通过

所以在这个角度上说,可能不能发挥JSON的“精炼”的特点,当然这可能更多的针对输入,输出上应该对JSON会更友好些。


但无论如何,对用户都是友好的,透明的
19 楼 mechiland 2010-01-19  
这么写实现上没有问题,但感觉丢掉了JSON自带的类型支持。例如,对float, int, string, boolean等原生数据类型的支持,JSON是可以自描述的,而不用写上string:"abc", double: 1.0之类。

例如service.divide(1.0, 2.0), 我期待用JSON写起来应该是这样子的:

{buffalo-call: 'divide', parameters: [1.0, 2.0]}

例如Map的例子:

{buffalo-call: 'somemethod', parameters: [{id: 1, name: "Michael", gendor: true}, count: 2]}

这样写需要对json更加智能的处理。

你的实现仍然是没有问题的;只是这样写出来的协议对于xml没有本质的区别,对于客户端调用而言也没有太多的改善之处。
18 楼 itstarting 2010-01-19  
<p><span><span style="font-size: small;">
<h3 style="margin: 12pt 0cm; text-indent: 0cm;"><span lang="EN-US"><span style="font-size: large; font-family: Times New Roman;">net.buffalo.protocal.io.json.JsonStreamReader</span></span></h3>
</span></span></p>
<p> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p><span><span><span>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">正式写这个类了。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">开始很顺利,对于如下简单的测试用例,很快就</span><span lang="EN-US"><span style="font-family: Times New Roman;">PASS</span></span><span style="">了。</span></span></p>
<span><span><font>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
</font></span></span></span></span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<pre name="code" class="java"> private String simpleCall  = "[{'buffalo-call':''},{'method':'divide'},{'double':1},{'double':2}]";

public void testSimpleCall() throws Exception {
StringReader reader = new StringReader(simpleCall);
StreamReader streamReader = new JsonStreamReader(reader);
assertEquals("buffalo-call",streamReader.getNodeName());
streamReader.moveDown();
assertEquals("method",streamReader.getNodeName());
assertEquals("divide", streamReader.getValue());
streamReader.moveUp();
streamReader.moveDown();
assertEquals("double", streamReader.getNodeName());
assertEquals("1", streamReader.getValue());
streamReader.moveUp();
streamReader.moveDown();
assertEquals("double", streamReader.getNodeName());
assertEquals("2", streamReader.getValue());
}
</pre>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">然而对于复杂的参数,尤其是</span><span lang="EN-US"><span style="font-family: Times New Roman;">map</span></span><span style="">和</span><span lang="EN-US"><span style="font-family: Times New Roman;">list</span></span><span style="">这种存在复杂嵌套的部分,则暴露出了两个关键问题:</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">1</span></span><span style="">、</span><span lang="EN-US"><span style="font-family: Times New Roman;">moveUp/moveDown</span></span><span style="">对于</span><span lang="EN-US"><span style="font-family: Times New Roman;">XML</span></span><span style="">这种有明确封闭标签(如</span><span lang="EN-US"><span style="font-family: Times New Roman;">&lt;/double&gt;</span></span><span style="">)的,确实支持的非常好,但对于</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">却有些逻辑上的障碍:</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">不是特别方便</span><span lang="EN-US"><span style="font-family: Times New Roman;">/</span></span><span style="">合适表达层级关系,也无特别的好用以匹配关闭的标签;</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">2</span></span><span style="">、</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">表达样式我所提供的是否适合</span><span lang="EN-US"><span style="font-family: Times New Roman;">Buffalo</span></span><span style="">?</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">我所提供的</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">表达样式,可参考</span><span lang="EN-US"><span style="font-family: Times New Roman;">JsonStandardStreamReaderTest.java</span></span><span style="">。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span lang="EN-US"><span style="font-size: small; font-family: Times New Roman;"> </span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
17 楼 itstarting 2010-01-18  
<p><span style="font-size: small;"><span style="">
<p style="margin: 12pt 0cm; text-indent: 0cm;"><span style=""><strong>快速小结</strong></span></p>
</span></span></p>
<p> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"></span> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">上面版本的</span><span lang="EN-US"><span style="font-family: Times New Roman;">Reader</span></span><span style="">,并非一个符合</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo SteamReader</span></span><span style="">接口的通用的</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">解析器,充其量只能是一个</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo-call</span></span><span style="">请求</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">的解析器而已。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">另外,还是存在一些明显的问题的,且先不说性能,光就</span><span lang="EN-US"><span style="font-family: Times New Roman;">moveDown</span></span><span style="">和</span><span lang="EN-US"><span style="font-family: Times New Roman;">moveUp</span></span><span style="">逻辑的严谨性就够喝一壶。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">其中,已知的</span><span lang="EN-US"><span style="font-family: Times New Roman;">BUG有</span></span><span style="">:</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">1</span></span><span style="">、在单元测试用例</span></span><span style="font-size: 10pt; background: silver; color: #000000; line-height: 120%; font-family: 'Courier New';">testComplexTest</span><span style="font-size: small;"><span style="">中,我注释了两句</span><span lang="EN-US"><span style="font-family: Times New Roman;">assertEquals</span></span><span style="">,因为他们测试是不能通过的,主要还是</span><span lang="EN-US"><span style="font-family: Times New Roman;">moveUp</span></span><span style="">的逻辑可能还存在不完整不严谨。——当然了,一般人不会那么变态的</span><span lang="EN-US"><span style="font-family: Times New Roman;">moveUp</span></span><span style="">后还要看看是啥。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">2</span></span><span style="">、存在一些“潜规则”硬编码。比如我假定了第一个</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSONObject</span></span><span style="">就是</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo-call</span></span><span style="">,第二个</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSONObject</span></span><span style="">就是</span><span lang="EN-US"><span style="font-family: Times New Roman;">method</span></span><span style="">,第三个开始就是</span><span lang="EN-US"><span style="font-family: Times New Roman;">call</span></span><span style="">方法的参数——虽然</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo-call</span></span><span style="">确实如此——这也就是为什么说这个</span><span lang="EN-US"><span style="font-family: Times New Roman;">Reader</span></span><span style="">只能是一个</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo-call</span></span><span style="">请求</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">的解析器的根本原因。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">但是,通过上面</span><span lang="EN-US"><span style="font-family: Times New Roman;">Reader</span></span><span style="">的编写,让我更进一步了解了</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">的同时,也逐步尝试</span><span style="">约定了</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">协议表达的约定。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">总而言之,还是得写正宗的</span><span lang="EN-US"><span style="font-family: Times New Roman;">JsonStreamReader</span></span><span style="">,绕不开啊。</span></span></p>
<p> </p>
16 楼 itstarting 2010-01-18  
<p><span style=""><strong>net.buffalo.protocal.io.json.JsonStandardInputStreamReader</strong></span></p>
<p> </p>
<p><span style="">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">同</span><span lang="EN-US">XML</span><span style="">协议一样,完全是照葫芦画瓢的写了这个类:</span></p>
<pre name="code" class="java">package net.buffalo.protocal.io.json;

import java.io.IOException;
import java.io.InputStream;

import org.json.JSONArray;
import org.json.JSONException;

import net.buffalo.protocal.ProtocolException;
import net.buffalo.protocal.io.StreamException;
import net.buffalo.protocal.io.StreamReader;

/**
* The same as FastInputStreamReader
*
* @see FastInputStreamReader.java
*/
public class JsonStandardInputStreamReader extends JsonStandardStreamReader implements StreamReader {

private final InputStream in;

public JsonStandardInputStreamReader(InputStream in) {
this.in = in;
int ch;
try {
ch = readSingleChar();
for (; ch &gt; -1; ch = readSingleChar()) {
sbuf.append((char)ch);
}
} catch (IOException e) {
throw new StreamException(e);
}
try{
all = new JSONArray(sbuf.toString());
len = all.length();
}catch(JSONException e){
throw new ProtocolException("Invalid JSON String.");
}
moveDown();
}

public void close() {
try {
in.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

protected int readSingleChar() throws IOException {
return in.read();
}
}
</pre>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">此时可以完整的测试了,且慢,</span><span lang="EN-US">Writer</span><span style="">还没写呢,咋测试啊——简单了,我的</span><span lang="EN-US">JsonStreamWriter</span><span style="">是拷贝</span><span lang="EN-US">XML</span><span style="">协议的过来的,此时:</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span lang="EN-US">JSON-&gt; JsonStandardInputStreamReader-&gt;</span><span style="">调用服务</span><span lang="EN-US">-&gt; JsonStreamWriter</span><span style="">,哈哈,回写还是用原来的</span><span lang="EN-US">XML</span><span style="">协议,怪是怪了点,但却是可以测试我的</span><span lang="EN-US">JsonStandardInputStreamReader</span><span style="">对</span><span lang="EN-US">JSON</span><span style="">协议的请求(</span><span lang="EN-US">Buffalo-Call</span><span style="">),基本还好用的:</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">请求界面:</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><br><img src="http://dl.iteye.com/upload/attachment/195262/0ab23746-d472-386e-ae9e-405436b28272.png" alt=""><br> <br></span>
</p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">看日志,用了</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span style="">协议,解析类是刚刚</span><span style="">出炉的</span><span style='font-size: 10pt; color: black; line-height: 120%; font-family: "Courier New";' lang="EN-US">JsonStandardInputStreamReader</span><span style="">:</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><br><img src="http://dl.iteye.com/upload/attachment/195264/ee01d7ee-5b22-3d4f-895d-e0cd16a8aeca.png" alt=""><br> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">结果呢:</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><br><img src="http://dl.iteye.com/upload/attachment/195266/afa9cd13-3728-3062-afc6-dae6ff40a7b6.png" alt=""><br> </p>
<span style="">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">正确,</span><span lang="EN-US"><span style="font-family: Times New Roman;">YEAH!</span></span><br> </p>
</span></span></p>
15 楼 itstarting 2010-01-18  
<p><span style=""><strong>net.buffalo.protocal.io.json.JsonStandardStreamReader</strong></span></p>
<p> </p>
<p><span style=""><span style="">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">第一个版本仅用于解析</span><span lang="EN-US">buffalo-call</span><span style="">的</span><span lang="EN-US">JsonStandardStreamReader.java</span><span style="">。</span></p>
<pre name="code" class="java">package net.buffalo.protocal.io.json;

import java.io.IOException;
import java.io.Reader;
import java.util.Stack;

import net.buffalo.protocal.ProtocalTag;
import net.buffalo.protocal.ProtocolException;
import net.buffalo.protocal.io.StreamException;
import net.buffalo.protocal.io.StreamReader;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
* The Implementation is not a general JSON StreamReader,
* just for parsing buffalo-call only.
*
* @author zhengxq
* @see JsonStreamReader.java
*/
public class JsonStandardStreamReader implements StreamReader {
private final Reader in;
protected StringBuffer sbuf = new StringBuffer();
private final JSONArray all;
private final int len;

protected Stack stack  = new Stack();
protected int depth = 0;

protected Tag currentTag;
private int pointer = 0;

protected Stack paramStack  = new Stack();
private int paramDepth = 0;
private JSONArray param; //temp for map or list
private int innerPointer = 0; //for map or list param

protected JsonStandardStreamReader() {
this.in = null;
this.all = null;
this.len = 0;
}

public JsonStandardStreamReader(Reader in){
this.in = in;
int ch;
try {
ch = readSingleChar();
for (; ch &gt; -1; ch = readSingleChar()) {
sbuf.append((char)ch);
}
} catch (IOException e) {
throw new StreamException(e);
}
try{
all = new JSONArray(sbuf.toString());
len = all.length();
}catch(JSONException e){
throw new ProtocolException("Invalid JSON String.");
}
moveDown();
}

/* move to next, and parse a Tag */
public void moveDown() {
JSONObject o = null;
if(pointer==0){ // buffalo-call
try{
o = all.getJSONObject(pointer);
pointer++;
if(o==null) throw new ProtocolException("The first tag should be 'buffalo-call'");
}catch(JSONException e){
throw new ProtocolException("Invalid JSON String.");
}catch(ProtocolException e){
throw e;
}
}else if(pointer==1){ // method
try{
o = all.getJSONObject(pointer);
pointer++;
if(o==null) throw new ProtocolException("The first tag should be 'method'");
}catch(JSONException e){
throw new ProtocolException("Invalid JSON String.");
}
}else{ // params
try{
//test for map or list
Tag test = (Tag) stack.get(depth - 1);
if(test.tag.equalsIgnoreCase(ProtocalTag.TAG_MAP)
|| test.tag.equalsIgnoreCase(ProtocalTag.TAG_LIST)) {
//it's map, then get the inner object
if(param == null){
// reset it
innerPointer = 0;
//parse it
param = (JSONArray)test.value;
}
if(innerPointer&gt;=param.length()) {
//try to restore
try{
Param p = (Param) paramStack.pop();
param = p.array;
innerPointer = p.pointer;
}catch(Exception e){
throw new ProtocolException("JSONArray in the param is out of bound : len="+len+" but innerPointer="+innerPointer);
}
}

o = (JSONObject) param.get(innerPointer);
innerPointer++;
}else{
// reset it
param = null;
innerPointer = 0;

if(pointer &gt;= len)
throw new ProtocolException("JSONArray is out of bound : len="+len+" but pointer="+pointer);
o = all.getJSONObject(pointer);
pointer++;
}
}catch(JSONException e){
throw new ProtocolException("Unexcepted error.");
}
}
parseTag(o);

stack.push(currentTag);
depth++;

if(currentTag.tag.equalsIgnoreCase(ProtocalTag.TAG_MAP)
|| currentTag.tag.equalsIgnoreCase(ProtocalTag.TAG_LIST)){
paramStack.push(new Param(param,innerPointer));
param = (JSONArray)currentTag.value;
innerPointer = 0;
}
}

public void moveUp() {
depth--;
currentTag = (Tag) stack.pop();

if(currentTag.tag.equalsIgnoreCase(ProtocalTag.TAG_MAP)
|| currentTag.tag.equalsIgnoreCase(ProtocalTag.TAG_LIST)){
currentTag = (Tag) stack.get(depth-1);
//restore it
if(currentTag.tag.equalsIgnoreCase(ProtocalTag.TAG_MAP)
|| currentTag.tag.equalsIgnoreCase(ProtocalTag.TAG_LIST)){
Param p = (Param) paramStack.pop();
param = p.array;
innerPointer = p.pointer;
}
}
}

/* get tag name from currentTag */
public String getNodeName() {
return currentTag.tag;
}

/* get tag value from currentTag */
public String getValue() {
return String.valueOf(currentTag.value);
}

/* test if there has more*/
public boolean hasMoreChildren() {
//test for map or list
Tag test = (Tag) stack.get(depth - 1);
if(test.tag.equalsIgnoreCase(ProtocalTag.TAG_MAP)
|| test.tag.equalsIgnoreCase(ProtocalTag.TAG_LIST)){
//it's map, then get the inner object
if(param == null){
//parse it
param = (JSONArray)test.value;
}
if((innerPointer+1)&lt;param.length()) return true;
}else if(test.tag.equalsIgnoreCase(ProtocalTag.TAG_CALL)
&amp;&amp; pointer&lt;all.length()) return true;
return false;
}

public void close() {
try {
in.close();
} catch (IOException e) {
throw new StreamException(e);
}
}

protected int readSingleChar() throws IOException {
return in.read();
}

// get value from a JSONObject, the key is a standard key
private Tag parseTag(JSONObject o){
Tag t = new Tag();
for(int i=0; i &lt; ProtocalTag.ALL_TYPED_TAGS.length; i++){
try{
t.tag = ProtocalTag.ALL_TYPED_TAGS[i];
t.value = o.get(t.tag);
currentTag = t;
return currentTag;
}catch(JSONException e){}
}
return null;
}

class Tag {
protected String tag;
protected Object value;
public Tag(){}
public Tag(String tag, Object value) {
this.tag = tag;
this.value = value;
}
}

class Param {
protected JSONArray array;
protected int pointer;
public Param(JSONArray ja, int p) {
this.array = ja;
this.pointer = p;
}
}
}
</pre>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">毋庸置疑:</span><span lang="EN-US">It’s buggy</span></p>
</span></span></p>
14 楼 itstarting 2010-01-18  
<p><span style="" lang="EN-US"><strong>net.buffalo.protocal.io.json.JsonStandardStreamReaderTest.java</strong></span></p>
<p><span style="" lang="EN-US">
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="">第一个版本的测试用例,很长,但对buffalo-call具有较好的覆盖度:</span></p>
</span></p>
<p><span style="">
<pre name="code" class="java">package net.buffalo.protocal.io.json;

import java.io.StringReader;

import junit.framework.TestCase;
import net.buffalo.protocal.io.StreamReader;

/**
*
* for json unit test
*
* @author zhengxq
* @see FastStreamReaderTest.java
*/
public class JsonStandardStreamReaderTest extends TestCase {
private String simpleCall  = "[{'buffalo-call':''},{'method':'divide'},{'double':1},{'double':2}]";
private String callWithMap = "[{'buffalo-call':''},{'method':'sum'}," +
"{'int':1}," +
"{'map':[{'type':java.util.HashMap},{'string':'key1'},{'string':'value1'},{'string':'key2'},{'string':'value2'}]}," +
"{'string':test}" +
"]";
private String hasMoreChildren = "[{'buffalo-call':''},{'method':'sum'}," +
"{'int':1}," +
"{'map':[" +
" {'type':java.util.HashMap}," +
" {'string':'type'}," +
" {'string':'name'}," +
" {'list':[{'type':'list'},{'length':3}," +
"  {'string':a}," +
"  {'int':2}," +
"  {'double':8.88}]}," +
"]}]";
private String complexTest = "[{'buffalo-call':''},{'method':'fullTypeTest'}," +
"{'boolean':1}," +
"{'date':20100118T154212Z}," +
"{'int':1}," +
"{'double':2.22},"+
"{'string':'Hello world'},"+
"{'list':["+
" {'type':''},"+
" {'length':2},"+
" {'int':100},"+
" {'string':hi}"+
" ]},"+
"{'map':[" +
" {'type':java.util.HashMap}," +
" {'string':key1}," +
" {'string':value1}," +
" {'string':key2}," +
" {'string':value2}," +
" {'string':java.util.ArrayList}," +
" {'list':[" +
"  {'type':''}," +
"  {'length':3}," +
"  {'int':1}," +
"  {'string':good}," +
"  {'string':baby}" +
" ]}" +
"]}," +
"{'double':3.33}" +
"]";


/* simpleCall */
public void testSimpleCall() throws Exception {
StringReader reader = new StringReader(simpleCall);
StreamReader streamReader = new JsonStandardStreamReader(reader);
assertEquals("buffalo-call",streamReader.getNodeName());
streamReader.moveDown();
assertEquals("method",streamReader.getNodeName());
assertEquals("divide", streamReader.getValue());
streamReader.moveUp();
streamReader.moveDown();
assertEquals("double", streamReader.getNodeName());
assertEquals("1", streamReader.getValue());
streamReader.moveUp();
streamReader.moveDown();
assertEquals("double", streamReader.getNodeName());
assertEquals("2", streamReader.getValue());
}

/* callWithMap */
public void testShoudReadNested() throws Exception {
StringReader reader = new StringReader(callWithMap);
StreamReader streamReader = new JsonStandardStreamReader(reader);
assertEquals("buffalo-call", streamReader.getNodeName());
streamReader.moveDown();
assertEquals("method", streamReader.getNodeName());
assertEquals("sum", streamReader.getValue());
streamReader.moveUp();
streamReader.moveDown();
assertEquals("int", streamReader.getNodeName());
assertEquals("1", streamReader.getValue());

streamReader.moveUp();
streamReader.moveDown();
assertEquals("map", streamReader.getNodeName());
streamReader.moveDown();
assertEquals("type", streamReader.getNodeName());
assertEquals("java.util.HashMap", streamReader.getValue());
streamReader.moveUp();
streamReader.moveDown();
assertEquals("string", streamReader.getNodeName());
assertEquals("key1", streamReader.getValue());
streamReader.moveUp();
streamReader.moveDown();
assertEquals("string", streamReader.getNodeName());
assertEquals("value1", streamReader.getValue());
streamReader.moveUp();
streamReader.moveDown();
assertEquals("string", streamReader.getNodeName());
assertEquals("key2", streamReader.getValue());
streamReader.moveUp();
streamReader.moveDown();
assertEquals("string", streamReader.getNodeName());
assertEquals("value2", streamReader.getValue());

streamReader.moveUp();
streamReader.moveUp();
}

/* hasMoreChildren */
public void testHasMoreChildren() throws Exception {
StringReader reader = new StringReader(hasMoreChildren);
StreamReader streamReader = new JsonStandardStreamReader(reader);
assertTrue(streamReader.hasMoreChildren());
streamReader.moveDown();
//then {'method':'sum'}
assertFalse(streamReader.hasMoreChildren());
streamReader.moveUp();

streamReader.moveDown();
streamReader.moveUp();
streamReader.moveDown();
//then {'map':[...]}
assertEquals("map",streamReader.getNodeName());
assertTrue(streamReader.hasMoreChildren());

streamReader.moveDown();
//then {'type':java.util.HashMap}
streamReader.moveUp();

streamReader.moveDown();
//then {'string':'type'}
streamReader.moveUp();

streamReader.moveDown();
//then {'string':'name'}
streamReader.moveUp();

streamReader.moveDown();
//then {'list':[...]}
assertTrue(streamReader.hasMoreChildren());
assertEquals("list",streamReader.getNodeName());

while(streamReader.hasMoreChildren()) {
streamReader.moveDown();
streamReader.moveUp();
}

streamReader.moveUp();
assertEquals("map",streamReader.getNodeName());

assertFalse(streamReader.hasMoreChildren());
}

/**
*  more complex test.
*  //boolean、date、int、long、null、string、list、map、double
*  var t1 = true;//
*  var t2 = new Date();
*  var t3 = 1;//int
*  var t4 = parseFloat("2.22");
*  //var t5 = null;
*  var t6 = "Hello world";
*  var t7 = [100,"hi"];//list
*  var t8 = {'key1':'value1','key2':'value2','java.util.ArrayList':[1,"good","baby"]};//map
*  var t9 = parseFloat("3.33");

*  buffalo.remoteCall("fullTypeService.fullTypeTest",[t1,t2,t3,t4,t6,t7,t8,t9], function(reply) {
*  $("result").value = reply.getResult();
*  },protocol)
*  @author zhengxq
*/
public void testComplexTest() throws Exception {
StringReader reader = new StringReader(complexTest);
StreamReader streamReader = new JsonStandardStreamReader(reader);
assertEquals("buffalo-call",streamReader.getNodeName());
assertTrue(streamReader.hasMoreChildren());
streamReader.moveDown();
//&lt;method&gt;fullTypeTest&lt;/method&gt;
assertEquals("method",streamReader.getNodeName());
assertEquals("fullTypeTest",streamReader.getValue());
assertFalse(streamReader.hasMoreChildren());
streamReader.moveUp();

streamReader.moveDown();
//&lt;boolean&gt;1&lt;/boolean&gt;
assertEquals("boolean",streamReader.getNodeName());
assertEquals("1",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;date&gt;20100118T154212Z&lt;/date&gt;
assertEquals("date",streamReader.getNodeName());
assertEquals("20100118T154212Z",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;int&gt;1&lt;/int&gt;
assertEquals("int",streamReader.getNodeName());
assertEquals("1",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;double&gt;2.22&lt;/double&gt;
assertEquals("double",streamReader.getNodeName());
assertEquals("2.22",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;string&gt;Hello world&lt;/string&gt;
assertEquals("string",streamReader.getNodeName());
assertEquals("Hello world",streamReader.getValue());
streamReader.moveUp();


streamReader.moveDown();
//&lt;list&gt;...&lt;/list&gt;
assertEquals("list",streamReader.getNodeName());
assertTrue(streamReader.hasMoreChildren());

streamReader.moveDown();
//&lt;type&gt;&lt;/type&gt;
assertEquals("type",streamReader.getNodeName());
streamReader.moveUp();

streamReader.moveDown();
//&lt;length&gt;2&lt;/length&gt;
assertEquals("length",streamReader.getNodeName());
assertEquals("2",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;int&gt;100&lt;/int&gt;
assertEquals("int",streamReader.getNodeName());
assertEquals("100",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;string&gt;hi&lt;/string&gt;
assertEquals("string",streamReader.getNodeName());
assertEquals("hi",streamReader.getValue());
streamReader.moveUp();

streamReader.moveUp();//&lt;/list&gt;

streamReader.moveDown();
//&lt;map&gt;...&lt;/map&gt;
assertEquals("map",streamReader.getNodeName());
assertTrue(streamReader.hasMoreChildren());

streamReader.moveDown();
//&lt;type&gt;java.util.HashMap&lt;/type&gt;
assertEquals("type",streamReader.getNodeName());
assertEquals("java.util.HashMap",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;string&gt;key1&lt;/string&gt;
assertEquals("string",streamReader.getNodeName());
assertEquals("key1",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;string&gt;value1&lt;/string&gt;
assertEquals("string",streamReader.getNodeName());
assertEquals("value1",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;string&gt;key2&lt;/string&gt;
assertEquals("string",streamReader.getNodeName());
assertEquals("key2",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;string&gt;value2&lt;/string&gt;
assertEquals("string",streamReader.getNodeName());
assertEquals("value2",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;string&gt;java.util.ArrayList&lt;/string&gt;
assertEquals("string",streamReader.getNodeName());
assertEquals("java.util.ArrayList",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;list&gt;...&lt;/list&gt;
assertEquals("list",streamReader.getNodeName());
assertTrue(streamReader.hasMoreChildren());

streamReader.moveDown();
//&lt;type&gt;&lt;/type&gt;
assertEquals("type",streamReader.getNodeName());
streamReader.moveUp();

streamReader.moveDown();
//&lt;length&gt;3&lt;/length&gt;
assertEquals("length",streamReader.getNodeName());
assertEquals("3",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;int&gt;1&lt;/int&gt;
assertEquals("int",streamReader.getNodeName());
assertEquals("1",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;string&gt;good&lt;/string&gt;
assertEquals("string",streamReader.getNodeName());
assertEquals("good",streamReader.getValue());
streamReader.moveUp();

streamReader.moveDown();
//&lt;string&gt;baby&lt;/string&gt;
assertEquals("string",streamReader.getNodeName());
assertEquals("baby",streamReader.getValue());
streamReader.moveUp();
//assertEquals("list",streamReader.getNodeName());

streamReader.moveUp();//&lt;/list&gt;
assertEquals("map",streamReader.getNodeName());
streamReader.moveUp();//&lt;/map&gt;
assertEquals("buffalo-call",streamReader.getNodeName());

streamReader.moveDown();
//&lt;double&gt;3.33&lt;/double&gt;
assertEquals("double",streamReader.getNodeName());
assertEquals("3.33",streamReader.getValue());
streamReader.moveUp();

//assertEquals("buffalo-call",streamReader.getNodeName());
assertFalse(streamReader.hasMoreChildren());
}
}
</pre>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
13 楼 yvfish 2010-01-18  
多年以后,一个贴子,引起我对Buffalo的回忆,感叹时光流逝,物是人非。。。
12 楼 itstarting 2010-01-18  
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">经与</span><span lang="EN-US"><span style="font-family: Times New Roman;">Michael</span></span><span style="">沟通,印证了我对于性能的猜想:</span></span></p>
<p>
</p>
<table class="MsoTableGrid" style="border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0"><tbody><tr style="">
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; background-color: transparent;" width="568" valign="top">
<p style="text-indent: 21pt;"><span style="">没错。如果用<span lang="EN-US">dom, </span>意味着使用通用的<span lang="EN-US">xml</span>解析根据我的测试,当时使用最快的<span lang="EN-US">xpp3</span>的<span lang="EN-US">xml</span>解析器都无法满足我的性能期待。</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 12pt; text-indent: 21pt;"><span lang="EN-US"><span style="font-size: small; font-family: Times New Roman;">On 1 16, 2010 7:52 PM, "zhengxianquan" wrote:</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 20pt;"><span style="font-size: 10pt; line-height: 120%; font-family: Verdana;" lang="EN-US">Michael</span><span style="">:</span><span style="font-size: 10pt; line-height: 120%; font-family: Verdana;" lang="EN-US"> </span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 20pt;"><span style="">我已经开展了</span><span style="font-size: 10pt; line-height: 120%; font-family: Verdana;" lang="EN-US">JSON</span><span style="">协议的相关开发工作。</span><span style="font-size: 10pt; line-height: 120%; font-family: Verdana;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 20pt;"><span style="">然而对照</span><span style="font-size: 10pt; line-height: 120%; font-family: Verdana;" lang="EN-US">XML</span><span style="">协议,我有个问题没想明白:为什么</span><span style="font-size: 10pt; line-height: 120%; font-family: Verdana;" lang="EN-US">StreamReader</span><span style="">要一个字符一个字符的解析,何不直接读出来后,直接转化为</span><span style="font-size: 10pt; line-height: 120%; font-family: Verdana;" lang="EN-US">DOM</span><span style="">再处理?</span><span style="font-size: 10pt; line-height: 120%; font-family: Verdana;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 20pt;"><span style="">这其中难道有什么考虑吗?性能?</span><span style="font-size: 10pt; line-height: 120%; font-family: Verdana;" lang="EN-US"> </span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 20pt;"><span style="">对于</span><span style="font-size: 10pt; line-height: 120%; font-family: Verdana;" lang="EN-US">JSON</span><span style="">协议,在表达格式上有什么建议?</span><span style="font-size: 10pt; line-height: 120%; font-family: Verdana;" lang="EN-US"></span></p>
</td>
</tr></tbody></table>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">但正如我之前的考虑那样,我打算先做一次性读入</span><span lang="EN-US"><span style="font-family: Times New Roman;">-&gt;</span></span><span style="">解析为</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSONObject-&gt;</span></span><span style="">再基于现有</span><span lang="EN-US"><span style="font-family: Times New Roman;">StreamReader</span></span><span style="">接口实现系列方法的第一个版本,命名为</span><span lang="EN-US"><span style="font-family: Times New Roman;">JsonStandardStreamReader.java</span></span><span style="">。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">然而,这个</span><span lang="EN-US"><span style="font-family: Times New Roman;">JsonStandardStreamReader.java</span></span><span style="">只能是一个</span><span lang="EN-US"><span style="font-family: Times New Roman;">buffalo-call</span></span><span style="">的实现,不具有原有</span><span lang="EN-US"><span style="font-family: Times New Roman;">XML</span></span><span style="">协议下作为</span><span lang="EN-US"><span style="font-family: Times New Roman;">Reader</span></span><span style="">的广泛通用性(可不限制于Buffalo):</span><span lang="EN-US"><span style="font-family: Times New Roman;">The Implementation is not a general JSON StreamReader, just for parsing buffalo-call only.</span></span><span style="">”。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">协议的表达格式经过多番测试验证,需要调整一下,举例如下:</span></span></p>
<p><span style="">
<pre name="code" class="java">[{'buffalo-call':''},{'method':'divide'},{'double':1},{'double':2}]</pre>
</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">或者:</span></span></p>
<p><span style="">
<pre name="code" class="java">[{'buffalo-call':''},{'method':'sum'},{'int':1},{'map':[{'type':java.util.HashMap},{'string':'key1'},{'string':'value1'},{'string':'key2'},{'string':'value2'}]},{'string':test}]</pre>
</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">基于</span><span lang="EN-US"><span style="font-family: Times New Roman;">TDD</span></span><span style="">来做。目前的<span lang="EN-US"><span style="font-family: Times New Roman;">JsonStandardStreamReader已经可以解析上述的协议。</span></span></span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small; font-family: Times New Roman;"><span style=""><span lang="EN-US">接下来将枚举各种buffalo-call的可能,尽可能的保证单元测试下的覆盖率。</span></span></span></p>
11 楼 itstarting 2010-01-18  
非常感谢楼上的推荐,昨天粗略看了下,你的beetle框架确实比较完整,值得学习,但个中的精华还没体会到,你可进一步开贴宣讲。

但我的目标不是简单的用AJAX框架,而是通过与原创作者沟通,结合自己的思考,学习和完善个人觉得比较精到的AJAX框架Buffalo
10 楼 HenryYu 2010-01-17  
用不得改造那么累了,用我的beetle框架吧,其中基于web层ajax实现,通信协议用的就是json,可以实现java对象(包括列表等)与javascript对象透明转换,可以随意与当前流行的UI的js库整合。
9 楼 itstarting 2010-01-16  
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span>通过进一步学习</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span>发现,正如</span><span lang="EN-US"><span style="font-family: Times New Roman;">Michael</span></span><span>说的“有些需要特殊解决的问题,在</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span>中仍然存在,特别是类型的处理。你仍然不得不在</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span>中加上类似于</span><span lang="EN-US"><span style="font-family: Times New Roman;">type</span></span><span>的特殊属性并在后端进行处理”,我决定中庸一些,不寻求绝对精简的</span><span lang="EN-US"><span style="font-family: Times New Roman;">JSON</span></span><span>,而是要求所有的值,都给我老老实实带上</span><span lang="EN-US"><span style="font-family: Times New Roman;">Type</span></span><span>。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span>格式举例:</span></span></p>
<p><span style="font-size: small;"><span>
<pre name="code" class="java">{'buffalo-call':[{'method':divide},{'double':1},{'double':2}]}</pre>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
</span></span>
</p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>

<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span>然而,在编写协议解析的时候,出现了第一个疑问:<strong>这个协议需要一个字符一个字符来解析吗,何不直接转化为JSONObject再处理,岂不是更方便?</strong></span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span>这个问题同样适用于XML:何不直接读取inputStream后,转化为标准的DOM对象后再处理?</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span>难道还有其他什么考虑吗?</span></span></p>
8 楼 itstarting 2010-01-15  
<p><strong>改造:BuffaloWorker.java</strong></p>
<p> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">根据</span><span lang="EN-US"><span style="font-family: Times New Roman;">BuffaloInvoker</span></span><span style="">的调整而微调:</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 20pt;"><span style='font-size: 10pt; color: black; line-height: 120%; font-family: "Courier New";' lang="EN-US">BuffaloInvoker.<em>getInstance</em>()</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">改为:</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 20pt;"><span style='font-size: 10pt; color: black; line-height: 120%; font-family: "Courier New";' lang="EN-US">BuffaloInvoker.<em>getInstance</em>(getProtocol())</span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">如下:</span></span></p>
<pre name="code" class="java">//get the right BuffaloInvoker instance, and invoke it
//BuffaloInvoker.getInstance().invoke(service, inputStream, new OutputStreamWriter(response.getOutputStream(), OUTPUT_ENCODING));
BuffaloInvoker.getInstance(getProtocol()).invoke(service, inputStream, new OutputStreamWriter(response.getOutputStream(), OUTPUT_ENCODING));
</pre>
<p> </p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;"><strong>至此,我个人感觉结构性的代码调整已经完成。</strong></span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;">下面所做的,就是我们刚才说到的三个重头戏。</span></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""></span></p>
<p class="MsoNormal" style="margin: 6pt 0cm 0pt; text-indent: 21pt;"><span style=""><span style="font-size: small;"><strong>但涉及到协议的代码,将非常细节,要求精通Buffalo的XML协议细节,并要求对JSON有较好的把握,所以整体难度也会更大写,从进度上看可能需要点时间了。</strong></span></span></p>

相关推荐

    基于java的国产Ajax框架 Buffalo.zip

    而在Java领域,虽然有如jQuery、Prototype等JavaScript库提供了Ajax功能,但针对国内开发者需求,一些国产Ajax框架应运而生,其中就包括了Buffalo框架。 Buffalo框架是专为Java开发者设计的轻量级、高性能的Ajax...

    基于java的开发源码-国产Ajax框架 Buffalo.zip

    **Ajax框架Buffalo详解** Ajax(Asynchronous JavaScript and XML)技术是现代Web开发中的关键组成部分,它使得网页能够实现异步更新,提升了用户体验。而基于Java的Ajax框架Buffalo则是国内开发者为解决这一需求而...

    国产Ajax框架 Buffalo源码

    无论服务器返回的是XML、JSON还是其他格式,框架都能自动解析并转换为JavaScript对象,供前端使用。这得益于框架内建的强大的数据解析库,它能处理各种常见的数据格式,大大简化了数据处理的步骤。 此外,Buffalo还...

    ajax十大框架

    根据给定的信息,我们可以梳理出以下关于Ajax框架的相关知识点: ### 1. Prototype Prototype 是一个功能强大的 JavaScript 库,它扩展了 DOM API,并提供了一系列便捷的方法和对象。该库非常优雅,支持丰富的 ...

    AJAX(Buffalo)配置使用

    AJAX,全称为Asynchronous JavaScript and XML,是一种在无需刷新整个网页的情况下,能够更新部分网页内容的技术。在实际开发中,它极大地提升了用户体验,让用户在交互时感觉更加流畅。本篇将详细介绍AJAX的配置与...

    buffalo-2.0.1-bin.zip

    Buffalo-2.0.1-bin.zip是一款专为开发者设计的高效、易用且功能丰富的Ajax工具框架。Ajax,即Asynchronous JavaScript and XML,是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。Buffalo框架正是...

    10大js框架 javaScript框架

    在探讨“十大JavaScript框架”这一主题时,我们深入解析了多个关键框架,这些框架在现代Web开发中扮演着至关重要的角色。以下是对每个框架的详细分析: ### 1. Prototype Prototype是最早一批的JavaScript库之一,...

    struts2 buffalo 资源

    "Struts2 Buffalo 资源"这个标题可能指的是一个包含了Struts2框架特定版本(2.0.14)以及与其相关的Buffalo AJAX技术框架的资源集合。 Buffalo框架是Struts2的一个插件,专门用于处理AJAX请求。它简化了在Struts2...

    java开源包3

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    java开源包1

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    java开源包11

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    java开源包2

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    java开源包6

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    java开源包5

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    java开源包10

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    java开源包4

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    java开源包8

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    java开源包7

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

    java开源包9

    jSIP这个Java包目标是用Java实现SIP(SIP:Session Initiation Protocol)协议及SIP协议的其它扩展部 分。 Java表达式语法解析库 parboiled parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG...

Global site tag (gtag.js) - Google Analytics