使用BlazeDS进行Java和纯actionscript项目通信
前段时间在帮着做一个网络模块,背景是一个actionscript的项目和后台服务器进行数据交换。最后选择了BlazeDS的解决方案,使用HTTP封装的AMF协议进行通信。交换的数据中有各种数组和自定义类,blazeDS基本上都能自动序列化和反序列化,因此用的比较舒服。但一开始配置环境的时候遇到了各种奇怪的问题,特别有一个问题网上搜索只有在一个post里提到,因此很值得记录。
搭建BlazeDS服务器
因为BlazeDS实质上是tomcat webapp,因此我用的是Eclipse+Web Tools Platform搭建的服务器。建立Dynamic Web Project之后,将blazeds.war里面的META-INF和WEB-INF解压到WebContent里面,就完成了服务器的初步搭建(so easy~)。在Eclipse里面用Run on Server,接下来一系列常规设置tomcat就行了。
在FlashBuilder中,我一开始是选择的Flex项目进行测试(因为纯actionscript项目使用BlazeDS会麻烦非常多,容后再表)。在建立项目的时候可以选择服务器技术-BlazeDS:
提示说“无法访问 Web 服务器。服务器可能没有运行,或者 Web 根文件夹或根 URL 可能无效”,但实际上是已经在Eclipse里面运行了服务器。这就是我纠结的第一个问题。
后来发现,Eclipse WTP在默认部署的时候,是将网站部署到workspace metadata文件夹;Flex在验证服务器的时候,很有可能是在文件夹里添加某些内容然后尝试远程访问——这个很像Google site这样上传随机文件的样子。然而用过的人都知道,WTP在刷新服务器内容的时候是有时间差的(譬如修改了代码,会提示同步中…),这就是问题所在。最后我通过将网站部署位置修改到tomcat文件夹下来解决:
修改默认tomcat部署位置
通常情况下,会发现这些内容都是灰色的!我是通过删除tomcat服务器下的网站,清理之后重新打开,就如下图所示,可以修改了
将部署位置修改以后,FlashBuilder表示能正常连上了~
具体怎么使用BlazeDS服务器:修改配置文件、编写自定义类之类的,都比较简单,查阅官方文档就行了。比较简单的就搞定了Flex与Java之前的互相通信。
纯ActionScript项目使用BlazeDS
网上绝大部分(包括教程)都是如何使用Flex项目进行数据通信,ActionScript版本的很难找到。这一部分我纠结了特别长的时间,主要遇到了以下几个问题,在这里分享一下。
导入mx.rpc.*等
默认的AS项目比Flex项目少引用了不少东西,这里需要手动加上:framework.swc, rpc.swc。但是在加上framework.swc之后,还遇到了“无法为区域设置zh_CN解析资源束xxx解决方法”一串错误:在actionscript构建路径-库路径中,将C:\Program Files (x86)\Adobe\Adobe Flash Builder 4.6\sdks\4.6.0\frameworks\locale\zh_CN作为swc文件夹导入。
不使用services-config.xml配置
在Flex中,通过指定services-config.xml(本质是在编译的时候加上-services标签),可以很方便的使用
<mx:RemoteObject id="helloRemoteObject" destination="helloWorld" fault="faultHandler(event)" result="resultHandler(event)">; |
但是在Actionscrpit项目中,我指定xml编译一直不能成功使用。后来我自己使用AS3代码实现了等价的功能
var ro:RemoteObject = new RemoteObject(); |
这个就相当于调用远程对象的sayHello方法。
Error #1034
TypeError: Error #1034: Type Coercion failed: cannot convert Object@13e9921 to mx.messaging.messages.ErrorMessage.
这个问题是最值得记录的问题,也是我遇到的最关键的问题。最后在StackOverflow找到了答案:没有绑定。反正当时在网上搜了很久,都只有这一个地方找到。
Flex的.mxml文件本质上会编译出一堆.as文件(通过编译器指令-keep-generated-actionscript=true),对比发现有这样一句初始化命令flash.net.registerClassAlias()
public static function registerClassAliases():void |
这些语句的意思是说,将本地的as类和远程的java类对应起来(诸如flex.messaging.messages.*
都在blazeds.war里面的jar中实现了)。这样在Flex-Java通信的时候,就知道序列化和反序列化对应的是什么类了。
我估计是没有初始化的情况下,返回的基本类型(我当时是返回了一个String)不知道如何反序列化这样的情况。
所谓[RemoteClass(alias=)]
标签
除了基本的一些类型和数组之外,AMF协议可以进行自定义类的序列化。但是需要在AS代码中进行绑定,例如
[Bindable] |
但是,一如既往的,在actionscript中使用不能。最后发现这个问题和上个问题类似——对比.mxml生成的.as代码可以发现,这个metadata其实就是这句话
registerClassAlias("me.qiankanglai.test",Test); |
自此问题解决~
ps.当时做的时候还在纠结要不要用node.js+websocket,或者说AMF+socket的架构。最后出于开发风险和现有要求的考虑,用了HTTP+AMF的架构实现,估计问题也不大。
ps2.看了Zynga通信框架,感觉蛋定了好多!话说云服务真是个好东西啊。