AMF(Action Message Format)在开发Flash/Flex应用中使用频率是非常高的,相对普通的HTTP、WebService的SOAP等多种数据通信方式的效率更高,有人曾经做过这方面的测试,详细可以访问:
http://xinsync.xju.edu.cn/index.php/archives/2162
。本文将结合FluorineFx来提供通信服务接口,在客户端通过Flex来访问,简单的介绍下关于使用FluorineFx的AMF(Action Message Format)协议通信的用法。
通过FluorineFx网站来宿主该远程服务,通过Flex的配置文件services-config.xml配置远程访问的AMF连接通道。
首先建立一个FluorineFx服务库,并建立一个数据传输对象(DTO),为该对象添加
[FluorineFx.TransferObject]表示该对象可以用作于FluorineFx的数据传输对象,这个对象将会在本文后面用到,如下代码块:
namespace
FxDotNet.Services.DTO
{
[FluorineFx.TransferObject]
public class Book
{
public int ID { get ; set ; }
public string Name { get ; set ; }
public string Author { get ; set ; }
public double Price { get ; set ; }
public Book()
{ }
public Book( int id, string name, string author, double price)
{
this .ID = id;
this .Name = name;
this .Author = author;
this .Price = price;
}
}
}
{
[FluorineFx.TransferObject]
public class Book
{
public int ID { get ; set ; }
public string Name { get ; set ; }
public string Author { get ; set ; }
public double Price { get ; set ; }
public Book()
{ }
public Book( int id, string name, string author, double price)
{
this .ID = id;
this .Name = name;
this .Author = author;
this .Price = price;
}
}
}
接下来就需要提供一个FluorineFx的远程服务(即标记有[RemotingService]的对象),通过该服务提供对外访问的方法接口,如下代码块:
namespace
FxDotNet.Services
{
[RemotingService]
public class DataServices
{
public DataServices()
{
}
/// <summary>
/// 获取服务端的系统时间
/// </summary>
/// <returns></returns>
public string GetServerTime()
{
return DateTime.Now.ToString();
}
public ArrayCollection GetBooks()
{
ArrayCollection array = new ArrayCollection();
array.Add( new Book( 1 , " 三国演义 " , " 罗贯中 " , 100.00 ));
array.Add( new Book( 2 , " 西游记 " , " 吴承恩 " , 200.00 ));
array.Add( new Book( 3 , " 水浒传 " , " 施耐庵 " , 300.00 ));
array.Add( new Book( 4 , " 红楼梦 " , " 曹雪芹 " , 400.00 ));
return array;
}
}
}
{
[RemotingService]
public class DataServices
{
public DataServices()
{
}
/// <summary>
/// 获取服务端的系统时间
/// </summary>
/// <returns></returns>
public string GetServerTime()
{
return DateTime.Now.ToString();
}
public ArrayCollection GetBooks()
{
ArrayCollection array = new ArrayCollection();
array.Add( new Book( 1 , " 三国演义 " , " 罗贯中 " , 100.00 ));
array.Add( new Book( 2 , " 西游记 " , " 吴承恩 " , 200.00 ));
array.Add( new Book( 3 , " 水浒传 " , " 施耐庵 " , 300.00 ));
array.Add( new Book( 4 , " 红楼梦 " , " 曹雪芹 " , 400.00 ));
return array;
}
}
}
通过FluorineFx网站来宿主该远程服务,通过Flex的配置文件services-config.xml配置远程访问的AMF连接通道。
<
channels
>
< channel-definition id ="my-amf" class ="mx.messaging.channels.AMFChannel" >
< endpoint uri ="http://{server.name}:{server.port}/{context.root}/Gateway.aspx" class ="flex.messaging.endpoints.AMFEndpoint" />
< properties >
</ properties >
</ channel-definition >
</ channels >
< channel-definition id ="my-amf" class ="mx.messaging.channels.AMFChannel" >
< endpoint uri ="http://{server.name}:{server.port}/{context.root}/Gateway.aspx" class ="flex.messaging.endpoints.AMFEndpoint" />
< properties >
</ properties >
</ channel-definition >
</ channels >
FluorineFx提供的远程服务(RemotingService),使用Flex、Flash或Silverlight开发的客户端都是可以访问的,要实现客户端的远程调用其实是很简单的,这里以Flex作为示例进行演示,设置通信协议为AMF3,然后直接调用当前连接到服务器端连接对象的call()方法就可以实现远程调用,详细请查看下面完整的Flex示例。
<?
xml version
=
"
1.0
"
encoding
=
"
utf-8
"
?>
< mx:Application xmlns:mx = " http://www.adobe.com/2006/mxml " layout = " absolute " creationComplete = " init() " fontSize = " 12 " >
< mx:Script >
<! [CDATA[
import mx.collections.ArrayCollection;
import mx.controls.List;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
private var nc:NetConnection;
private var rs:Responder;
private function init(): void
{
nc = new NetConnection();
rs = new Responder(onResult,onStatus);
nc.objectEncoding = ObjectEncoding.AMF3;
nc.connect( " http://localhost:2311/FxDotNet.Web/Gateway.aspx " );
nc.client = this ;
}
private function onResult(result:String): void
{
this .lbServerTime.text = " 服务端系统时间为: " + result;
}
private function onStatus( event :Object): void
{
trace( " Error " );
}
private function getServerTime( event :MouseEvent): void
{
// 服务器端所提供的RemotingService的全限定名
nc.call( " FxDotNet.Services.DataServices.GetServerTime " ,rs);
}
]] >
</ mx:Script >
< mx:Button x = " 19 " y = " 28 " label = " 获取服务器系统时间 " click = " getServerTime(event) " />
< mx:Label x = " 19 " y = " 60 " width = " 402 " id = " lbServerTime " />
</ mx:Application >
< mx:Application xmlns:mx = " http://www.adobe.com/2006/mxml " layout = " absolute " creationComplete = " init() " fontSize = " 12 " >
< mx:Script >
<! [CDATA[
import mx.collections.ArrayCollection;
import mx.controls.List;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
private var nc:NetConnection;
private var rs:Responder;
private function init(): void
{
nc = new NetConnection();
rs = new Responder(onResult,onStatus);
nc.objectEncoding = ObjectEncoding.AMF3;
nc.connect( " http://localhost:2311/FxDotNet.Web/Gateway.aspx " );
nc.client = this ;
}
private function onResult(result:String): void
{
this .lbServerTime.text = " 服务端系统时间为: " + result;
}
private function onStatus( event :Object): void
{
trace( " Error " );
}
private function getServerTime( event :MouseEvent): void
{
// 服务器端所提供的RemotingService的全限定名
nc.call( " FxDotNet.Services.DataServices.GetServerTime " ,rs);
}
]] >
</ mx:Script >
< mx:Button x = " 19 " y = " 28 " label = " 获取服务器系统时间 " click = " getServerTime(event) " />
< mx:Label x = " 19 " y = " 60 " width = " 402 " id = " lbServerTime " />
</ mx:Application >
同样可以使用AMF来做大数据的传输,比如要传递一个集合、数组、DataTable或是DataSet等,下面以集合做为示例演示,ActionScript 3.0中新增了ArrayCollectin类,FluorineFx在服务器端对ActionScript 3.0的ArrayCollection对进行了序列化映射封装,服务端
FluorineFx.AMF3.ArrayCollection类型的对象可以直接被客户端的ArrayCollection所接收。
如上面FluorineFx所提供的远程服务接口中的GetBooks()方法,Flex调用此方法就会得到一个ArrayCollection对象,通过调试跟踪返回的数据可以很清楚的分析这些数据,如下图示:
详细请看下面的Flex完整示例代码:
<?
xml version
=
"
1.0
"
encoding
=
"
utf-8
"
?>
< mx:Application xmlns:mx = " http://www.adobe.com/2006/mxml " layout = " absolute " fontSize = " 12 "
width = " 541 " height = " 302 " creationComplete = " init() " >
< mx:Script >
<! [CDATA[
import mx.collections.ArrayCollection;
import mx.controls.List;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
private var nc:NetConnection;
private var rs:Responder;
private function init(): void
{
nc = new NetConnection();
rs = new Responder(onResult,onFault);
nc.objectEncoding = ObjectEncoding.AMF3;
nc.connect( " http://localhost:2311/FxDotNet.Web/Gateway.aspx " );
nc.client = this ;
}
private function getBook( event :MouseEvent): void
{
nc.call( " FxDotNet.Services.DataServices.GetBooks " ,rs);
}
private function onResult(result:ArrayCollection): void
{
this .bookGrid.dataProvider = result;
}
private function onFault( event :Object): void
{
trace( " Error " );
}
]] >
</ mx:Script >
< mx:Button x = " 44 " y = " 46 " label = " 获取图书信息 " click = " getBook(event) " />
< mx:DataGrid x = " 44 " y = " 78 " id = " bookGrid " >
< mx:columns >
< mx:DataGridColumn headerText = " 编号 " dataField = " ID " />
< mx:DataGridColumn headerText = " 书名 " dataField = " Name " />
< mx:DataGridColumn headerText = " 作者 " dataField = " Author " />
< mx:DataGridColumn headerText = " 价格 " dataField = " Price " />
</ mx:columns >
</ mx:DataGrid >
</ mx:Application >
< mx:Application xmlns:mx = " http://www.adobe.com/2006/mxml " layout = " absolute " fontSize = " 12 "
width = " 541 " height = " 302 " creationComplete = " init() " >
< mx:Script >
<! [CDATA[
import mx.collections.ArrayCollection;
import mx.controls.List;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
private var nc:NetConnection;
private var rs:Responder;
private function init(): void
{
nc = new NetConnection();
rs = new Responder(onResult,onFault);
nc.objectEncoding = ObjectEncoding.AMF3;
nc.connect( " http://localhost:2311/FxDotNet.Web/Gateway.aspx " );
nc.client = this ;
}
private function getBook( event :MouseEvent): void
{
nc.call( " FxDotNet.Services.DataServices.GetBooks " ,rs);
}
private function onResult(result:ArrayCollection): void
{
this .bookGrid.dataProvider = result;
}
private function onFault( event :Object): void
{
trace( " Error " );
}
]] >
</ mx:Script >
< mx:Button x = " 44 " y = " 46 " label = " 获取图书信息 " click = " getBook(event) " />
< mx:DataGrid x = " 44 " y = " 78 " id = " bookGrid " >
< mx:columns >
< mx:DataGridColumn headerText = " 编号 " dataField = " ID " />
< mx:DataGridColumn headerText = " 书名 " dataField = " Name " />
< mx:DataGridColumn headerText = " 作者 " dataField = " Author " />
< mx:DataGridColumn headerText = " 价格 " dataField = " Price " />
</ mx:columns >
</ mx:DataGrid >
</ mx:Application >
除了使用FluorineFx所提供的ArrayCollection外,同样可以使用我们熟悉的Object[],List<Object>,DataTable等常用类型来作为数据返回的类型,其中Object[]和List<Object>类型的数据返回到客户段能够直接被客户端所接收,如下使用Object[]作数据返回类型的代码块:
/*
************服务端方法************
*/
public Book[] GetBookArray()
{
Book[] book = new Book[]
{
new Book( 1 , " 三国演义 " , " 罗贯中 " , 100.00 ),
new Book( 2 , " 西游记 " , " 吴承恩 " , 200.00 ),
new Book( 3 , " 水浒传 " , " 施耐庵 " , 300.00 ),
new Book( 4 , " 红楼梦 " , " 曹雪芹 " , 400.00 )
};
return book;
}
/* ************客户端方法************ */
private function onResult(result:Array): void
{
//
}
public Book[] GetBookArray()
{
Book[] book = new Book[]
{
new Book( 1 , " 三国演义 " , " 罗贯中 " , 100.00 ),
new Book( 2 , " 西游记 " , " 吴承恩 " , 200.00 ),
new Book( 3 , " 水浒传 " , " 施耐庵 " , 300.00 ),
new Book( 4 , " 红楼梦 " , " 曹雪芹 " , 400.00 )
};
return book;
}
/* ************客户端方法************ */
private function onResult(result:Array): void
{
//
}
下面是以List<Object>类型返回的代码示例代码,客户段可以使用ArrayCollection直接接收:
/*
************服务端方法************
*/
/// <summary>
/// 以泛型类型返回给客户端
/// </summary>
/// <returns></returns>
public List < Book > GetBookList()
{
List < Book > list = new List < Book >
{
new Book( 1 , " 三国演义 " , " 罗贯中 " , 100.00 ),
new Book( 2 , " 西游记 " , " 吴承恩 " , 200.00 ),
new Book( 3 , " 水浒传 " , " 施耐庵 " , 300.00 ),
new Book( 4 , " 红楼梦 " , " 曹雪芹 " , 400.00 )
};
return list;
}
/* ************客户端方法************ */
private function onResult(result:ArrayCollection): void
{
//
}
/// <summary>
/// 以泛型类型返回给客户端
/// </summary>
/// <returns></returns>
public List < Book > GetBookList()
{
List < Book > list = new List < Book >
{
new Book( 1 , " 三国演义 " , " 罗贯中 " , 100.00 ),
new Book( 2 , " 西游记 " , " 吴承恩 " , 200.00 ),
new Book( 3 , " 水浒传 " , " 施耐庵 " , 300.00 ),
new Book( 4 , " 红楼梦 " , " 曹雪芹 " , 400.00 )
};
return list;
}
/* ************客户端方法************ */
private function onResult(result:ArrayCollection): void
{
//
}
如果要使用DataTable类型做方法的数据返回类型就需要注意下,服务器端直接返回DataTable类型的数据客户端是不能直接接收解析的,要使客户断方便解析所返回的DataTable类型数据,FluorineFx提供了DataTableTypeAttribute,为返回DataTable类型的方法加上DataTableTypeAttribute后返回给客户端,客户端就可以直接使用ArrayCollection接收了。
返回DataTable类型
关于FluorineFx的AMF就简单介绍这些,要想了解更多的Flex客户端与.NET服务器端通信,可以访问
这里 。
本文示例代码下载
FluorineFxAMF.rar
本文转自 beniao 51CTO博客,原文链接:http://blog.51cto.com/beniao/166131,如需转载请自行联系原作者