精华帖 (2) :: 良好帖 (5) :: 新手帖 (0) :: 隐藏帖 (15)
|
|||
---|---|---|---|
作者 | 正文 | ||
发表时间:2010-01-14
最后修改:2010-02-08
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完成集成测试。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|||
返回顶楼 | |||
发表时间:2010-01-14
Buffalo原有的架构,就这个扩展的角度而言,基本还是合理到位的,核心部分均通过简约的接口定义,与具体实现进行了分离,内部也合理的运用了较好的设计模式实践。所有这些,均为实现JSON协议的扩展和改造打下良好的基础。 考虑到原有XML协议已经非常成熟稳定,整体实现基于JSON协议的扩展思路是这样的: 1、 改造原有与XML协议耦合过高的代码; 2、 实现基于JSON的io读写接口; 3、重新编写/扩展客户端序列化、反序列化机制。
|
|||
返回顶楼 | |||
发表时间:2010-01-14
最后修改:2010-01-14
首当其冲的是,得搞定入口问题。如何确保双协议的同时支持是关键?
首先定义一个全局变量: Buffalo.DefaultProtocol="JSON";//XML or JSON
协议的选择应该考虑基于每次的remoteCall,而不是全部要么这样要么那样。 此时需要扩展Buffalo.Call,新增参数protocol,并新增两个方法:
然后在正式发出后台请求的地方(Buffalo._remoteCall),通过RequestHeader传递这个协议指令:
这样,这个指令就可以从后端的入口Servlet(ApplicationServlet)获得。 |
|||
返回顶楼 | |||
发表时间:2010-01-14
当然了,Buffalo.Call还需要增加json方法,类似于xml,用以产生json的请求。 为了方便,这里先写死了,先把simpleService.divide走通再说: // parse the call to json format // TODO: now just for test json: function(){ this._objects = []; var jsonstr = "{'buffalo-call':[{'method':divide},{'double':1},{'double':2}]}"; return jsonstr; },
这回轮到修订后端的入口Servlet,即ApplicationServlet.java。 定义一个类全局的变量: private static final String PROTOCOL_ATTR = "X-Buffalo-Protocol";
在doRequest中获得协议名称:
|
|||
返回顶楼 | |||
发表时间:2010-01-14
我很好奇的看到有8名高手投了隐藏贴,如果大家已经有好的实现,不妨发给我学习参考,谢谢!
|
|||
返回顶楼 | |||
发表时间:2010-01-15
最后修改:2010-01-15
经昨天晚上的分析,上述改动不应在ApplicationServlet做,而应该在AbstractRequestWorker.java。即上述在ApplicationServlet的修订无效。 此时要改造的是AbstractRequestWorker.java,即把原先打算在ApplicationServlet的改动,调整在此类做:
定义一个类全局的变量:
private static final String PROTOCOL_ATTR = "X-Buffalo-Protocol"; 新增getProtocol的方法:
在这个抽象类做有什么好处呢?能确保所有Worker都能共享此变量。
拿到以后怎么用呢?目前并没有现成的办法。 后面应该需要较大的改造力度了。
|
|||
返回顶楼 | |||
发表时间:2010-01-15
最后修改:2010-01-15
改造:BuffaloProtocal.java
经进一步分析发现,BuffaloWorker调用了BuffaloInvoker实例的invoke方法实现输入流的解析(unmarshal)和输出结果对象的序列化(marshal),而BuffaloInvoker所使用的是BuffaloProtocal的实例。 再看看BuffaloProtocal实例的代码就知道,这里存在大量耦合XML协议的部分。 解耦在所难免。 此类改造由此产生了两个目标: 1、 应该要能区别所用的协议; 2、 实例将根据不同的协议初始化对应的StreamReader和StreamWriter。 为此,首先增加了一个类的私有变量protocol,用以表达所用协议(这个变量后续需要重构,谁知道后续还会冒出什么协议呢,对吧):
private String protocol = "XML";
废弃原有获取单例的方式并增加新的需要明确协议的方式:
注意:我感觉上面这样写会有线程安全问题,不知道各位怎么看?
改变原有的marshal和unmarshal方法中直接绑定XML SteamReader及SteamWriter的做法,通过if…else来判断(先这样,看以后再重构):
注意了,这里我先定义了三个类,分别为: JsonStreamReader——实现io/SteamReader接口,用以解析JSON输入流; JsonInputStreamReader——这个得再确认,原先XML协议下的说法是Opera下有编码问题才做的,先照葫芦画瓢改造; JsonStreamWriter——实现io/SteamWriter接口,用以序列化执行结果并输出JSON流 上述三个类将是本次扩展实现以支持JSON协议的重中之重。
|
|||
返回顶楼 | |||
发表时间:2010-01-15
改造:BuffaloInvoker.java
根据BuffaloProtocal.java的改造而做出的适应性改造。 首先增加了一个类的私有变量protocol,用以表达所用协议:
废弃原有获取单例的方式并增加新的需要明确协议的方式:
三处BuffaloProtocal.getInstance()的地方,改为:BuffaloProtocal.getInstance(protocol)。
|
|||
返回顶楼 | |||
发表时间:2010-01-15
改造:BuffaloWorker.java
根据BuffaloInvoker的调整而微调: BuffaloInvoker.getInstance() 改为: BuffaloInvoker.getInstance(getProtocol()) 如下: //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));
至此,我个人感觉结构性的代码调整已经完成。 下面所做的,就是我们刚才说到的三个重头戏。
但涉及到协议的代码,将非常细节,要求精通Buffalo的XML协议细节,并要求对JSON有较好的把握,所以整体难度也会更大写,从进度上看可能需要点时间了。 |
|||
返回顶楼 | |||
发表时间:2010-01-16
最后修改:2010-01-16
通过进一步学习JSON发现,正如Michael说的“有些需要特殊解决的问题,在JSON中仍然存在,特别是类型的处理。你仍然不得不在JSON中加上类似于type的特殊属性并在后端进行处理”,我决定中庸一些,不寻求绝对精简的JSON,而是要求所有的值,都给我老老实实带上Type。 格式举例:
然而,在编写协议解析的时候,出现了第一个疑问:这个协议需要一个字符一个字符来解析吗,何不直接转化为JSONObject再处理,岂不是更方便? 这个问题同样适用于XML:何不直接读取inputStream后,转化为标准的DOM对象后再处理?
难道还有其他什么考虑吗? |
|||
返回顶楼 | |||