Flex访问blazeds java服务,网上的讲解、例子很多,因此本文不再赘述,本文假设大家都基本上了解flex和blazeds java服务。下面提出问题:
问题:假设发布到tomcat j2ee应用为http://localhost:8080/demo,则我们知道,其对应的blazeds servlet(messagebroker)为http://localhost:8080/demo/messagebroker,实际上flex的remoteobject在访问java blazeds服务时,地址就是http://localhost:8080/demo/messagebroker加上AMF或者其它的channel。
我们再假设,在remoting-config.xml文件中有一个blazeds服务,如下:
<destination id="demoService" channels="my-amf">
<properties>
<source>com.blazeds.DemoService</source>
<scope>application</scope>
</properties>
</destination>
此时,在flex客户端,我们只要定义一个remoteobject即可访问demoService,如下:
<fx:Declarations>
<mx:RemoteObject id="ro" destination=" demoService"/>
</fx:Declarations>
ro.method1() //调用demoService的mothod1方法
这里,我们就疑问了就创建了一个简单的remoteobject对象,只指定了destination,flex是如何知道remoteobject要访问哪个地址的blazeds服务?remoteobject的channelset flex是如何指定的?
剖析:
1)flex主应用启动的时候,会请求messagebroker,返回services-config.xml配置文件的信息,其实就是一个xml串(内部包含services结点信息、channel结点信息),如下图所示:
大家只要设置ServerConfig.as类的set xml函数断点,调试即可得到上图所示信息,ServerConfig的set xml函数代码:
public static function set xml(value:XML):void
{
serverConfigData = value;
// Reset cached Channels and ChannelSets.
_channelSets = {};
_clusteredChannels = {};
_unclusteredChannels = {};
}
大家已经很清楚的可以看到,上图所示信息都是我们几个配置文件的内容,services-config.xml、remoting-config.xml、proxy-config.xml和messaging-config.xml。大家尤其要注意的是红色矩形区域:
<endpoint uri="http://{server.name}:{server.port}/demo/..."/>
其实这应该是remoteobject访问blazeds服务的时候,真正的访问地址,那么flex是如何将该地址自动赋予给remoteobject的呢?
2)Channel.as类解析
Remoteobject动态调用mothod1方法后,真正向http://localhost:8080/demo/messagebroker发送请求之前,会创建channel。
Channel构造函数:public function Channel(id:String = null, uri:String = null),其中uri即刚才的<endpoint uri="http://{server.name}:{server.port}/demo/..."/>,channel会根据用户的访问地址自动计算真正的uri,替换server.name和server.port,代码如下:
private function calculateEndpoint():void { if (uri == null) { var message:String = resourceManager.getString( "messaging", "noURLSpecified"); throw new InvalidChannelError(message); }
var uriCopy:String = uri; var proto:String = URLUtil.getProtocol(uriCopy);
if (proto.length == 0) uriCopy = URLUtil.getFullURL(LoaderConfig.url, uriCopy);
if (!URLUtil.hasUnresolvableTokens()) { _isEndpointCalculated = false; return; }
uriCopy = URLUtil.replaceTokens(uriCopy);
// Now, check for a final protocol after relative URLs and tokens // have been replaced proto = URLUtil.getProtocol(uriCopy);
if (proto.length > 0) _endpoint = URLUtil.replaceProtocol(uriCopy, protocol); else _endpoint = protocol + ":" + uriCopy;
_isEndpointCalculated = true;
if (Log.isInfo()) _log.info("'{0}' channel endpoint set to {1}", id, _endpoint); } |
计算完毕之后,之后所有remoteobject实例访问blazeds服务都用该endpoint uri。