1.AMF的介绍:
AMF(是ActionMessage Format的缩写)是在flash和flex中remoting的一种方式格式
Flash 5开始就可以以XML或者“变量/值”配对输出格式向服务器传送数据。虽然这些数据能通过Flash编译器自动解析或者通过开发人员自行编写的代码手动解析, 但解析的速度慢。因为在解析过程中,XML需要按节点逐层处理数据。而且使用XML和“变量/值”配对格式处理的数据类型只能是字符型,数字也不例外。而FlashRemoting却能处理复杂数据类型, 比如对象、结构、数组,甚至可以是数据集,配合DataGrid组件可以很方便地显示数据。
为了处理复杂数据类型,采用一种独有的方式使Flash与应用服务器间可以来回传送数据势在必行。于是AMF应运而生。AMF是Adobe独家开发出来的通信协议,它采用二进制压缩,序列化、反序列化、传输数据,从而为Flash 播放器与Flash Remoting网关通信提供了一种轻量级的、高效能的通信方式。AMF最大的特色在于可直接将Flash内置对象,例如Object,Array, Date, XML,传回服务器端,并且在服务器端自动进行解析成适当的对象,这就减轻了开发人员繁复工作,同时也更省了开发时间。由于AMF采用二进制编码,这种方式可以高度压缩数据,因此非常适合用来传递大量的资料。数据量越大,FlashRemoting的传输效能就越高,远远超过Web Service。至于XML, LoadVars和loadVariables(),它们使用纯文本的传输方式,效能就更不能与FlashRemoting相提并论了。
注:原文http://baike.baidu.com/view/5965977.htm
2. AMF的数据封装格式优点
Flash加载外部http数据有很多封装方式,常用的数据封装格式有xml SOAP、json、webService和amf等。其中前面三个都是互联网通用的基于字符串的格式,而AMF是Adobe独家开发出来的封装格式,它和其他格式不一样的地方是基于二进制的,而且这种格式是Flash可以读取的。它的优点也显露出来了:1、由于基于二进制,而且没有像xml那样很多的冗余数据,传输同样的数据量体积会小很多。2、数据传输到Flash端可以直接读取,无需进行字符串解释等反序列化过程,效率也提高了。(amf有两种格式:AMF0和AMF3;Flash8之前的版本只支持AMF0,Flash9支持两种格式、不过flash使用AMF3应该效率会高点,因为AMF0是兼容之前版本用的)
然而amf是Adobe独家开发的,如果不清楚它的数据封装格式就无法用其它后台语言将数据封装成amf再传输到flash那里。然而目前有很多开源的框架支持amf,如php的amfphp、java的openamf等。
3.BlazeDS介绍
BlazeDS是一个基于服务器的Java远程调用(remoting)和Web消息传递(messaging)技术,使得后台的Java应用程序和运行在浏览器上的Flex应用程序能够相互通信。
3.1机器环境配置
Jdk: 下载并安装,同时配置环境变量(参考: http://blog.csdn.net/gangan1345/article/details/7935050)
Tomcat:下载并安装,如安装7.0以上版本无需配置环境变量,配置7.0以下版本,参照http://blog.chinaunix.net/space.php?uid=9195812&do=blog&id=2006311 此文章内容进行配置.
(我将Tomcat安装在C:\tomcat目录下,下文将提到此目录运用)
配置完成后,运行http://localhost:8080 查看Tomcat是否配置正确
3.2 BlazeDS 环境配置
1、下载blazeds-bin-4.0.1.21287.zip文件并解压,找到“blazeds.war”文件,并解压
2、将解压的文件复制到C:\tomcat\webapps文件夹下
3、打开目录:C:\tomcat\webapps
i. 你应该会看到一个名为“blaseds”的文件夹
ii. 在blaseds文件夹里,会有一个名为“WEB-INF”的文件夹
iii. 在WEB-INF文件夹里会有很多文件夹,其中有一个名为“classes”的文件夹。Flex应用程序需要使用到的Javaclass就是放到这个文件夹里的
iv. 还有一个名为“flex”的文件夹,它里面有一个remoting-config.xml,我们要在这个remoting-config.xml文件里添加destination结点来告诉Flex应用程序如何连接上Javaclass
3.3 HelloWorld例子
1、JAVA类编写
HelloWorld .java
package cn.java;
public class HelloWorld {
public HelloWorld()
{
}
public String getHelloWorld(){
return "Hello World!";
}
}
2) 编译这个Java文件并得到HelloWorld.class文件。在C:\tomcat\webapps\blazeds\WEB-INF\classes 目录下新建一个名为“cn”的文件夹,“cn”的文件夹中新建一个“java”文件夹,将HelloWorld.class文件复制到此目录下。
3) 打开C:\tomcat\webapps\blazeds\WEB-INF\flex\remoting-config.xml 这个文件,然后在</default-channels>标签之后和</service>标签之前添加以下结点(注意id属性和source结点的值,source结点描述了完整的包路径和类名):
<destination id="helloWorld">
<properties>
<source>cn.java.HelloWorld</source>
</properties>
</destination>
4) 重启Tomcat
2、Flex界面编写
1)界面代码如下Helloworld.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
<s:RemoteObject id="remoteObject" destination="helloWorld" source="cn.java.HelloWorld"
result="resultHandler(event)" fault="faultHandler(event)">
</s:RemoteObject>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.rpc.events.FaultEvent;
import mx.controls.Alert;
import mx.rpc.events.ResultEvent;
//申请注册别名,使切换模块后仍然能正常通信
import flash.net.registerClassAlias;
import mx.messaging.messages.RemotingMessage;
registerClassAlias("com.test.HelloWorld", HelloWorld); //这里才是重点
private function resultHandler(event:ResultEvent):void
{
// 显示收到的 "Hello World!" 数据
Alert.show(event.result.toString(), "提示");
}
private function faultHandler(event:FaultEvent):void
{
Alert.show(event.fault.toString(), "提示");
}
]]>
</fx:Script>
<s:Button label="发送" click="remoteObject.getHelloWorld()"/>
</s:Application>
2、项目属性配置
Flex编译器:附加的编译器参数,添加 -services"C:\tomcat\webapps\blazeds\WEB-INF\flex\services-config.xml"
Flex服务器,修改服务器类型,填写配置信息,并通过“验证配置”按钮进行校验,最后点“确定”按钮进行保存
配置如下
服务器技术 应用程序服务类型 J2EE ,使用远程对象访问服务 选择BlazeDs(B)
服务器位置
根文件夹:c:\tomcat\webapps\blazeds
根URL : http://localhost:8080/blazeds
上下文根目录:/blazeds
按F11测试,你看到一个叫“发送”的按钮,按一下它,会弹出“Hello World!”,这是后台发送过来的。至此,我得恭喜您!您成功了!
3.4 自定义对象调用
1、 JAVA类编写
1)代码如下
添加自定义对象cn.java.model.Person
package cn.java.model;
import java.io.Serializable;
public class Person implements Serializable{
private static final long serialVersionUID = 1365163904641383233L;
private String name;
private String sex;
private String age;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person [name=" + name + ", sex=" + sex + ", age=" + age
+ ", address=" + address + "]";
}
}
添加方法 cn.java.service.PersonService
package cn.java.service;
import java.util.ArrayList;
import cn.java.model.Person;
public class PersonService {
private static ArrayList<Person> plist = new ArrayList<Person>();
public void addPerson(Person person){
plist.add(person);
System.out.println("use addPerson Service......");
System.out.println(plist.toString());
}
public ArrayList<Person> getPerson(){
System.out.println("use getPersonList Service......");
System.out.println(plist.toString());
return plist;
}
public String sayHello(String name){
System.out.println("use sayHello Service......\n"+name);
return "欢迎你:"+name;
}
}
2)编译这个Java文件并得到 .class文件,并复制到C:\tomcat\webapps\blazeds\WEB-INF\classes目录下
3)打开C:\tomcat\webapps\blazeds\WEB-INF\flex\remoting-config.xml 这个文件,然后添加destination节点
<destination id="StockDataService">
<properties>
<source>com.liker.service.StockDataService</source>
</properties>
</destination>
4) 重启tomcat
2、Flex界面编写
1)界面代码如下
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
<s:RemoteObject id="remoteObject" destination="PersonService" fault="remoteObject_faultHandler(event)">
<s:method name="addPerson" result="method1_resultHandler(event)" fault="remoteObject_faultHandler(event)"/>
<s:method name="getPerson" result="method2_resultHandler(event)" fault="remoteObject_faultHandler(event)"/>
<s:method name="sayHello" result="method3_resultHandler(event)" fault="remoteObject_faultHandler(event)"/>
</s:RemoteObject>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
import cn.java.model.Person;
[Bindable]
public var person:Person = new Person();
[Bindable]
public var listPerson:ArrayCollection = new ArrayCollection();
protected function btnPerson_clickHandler(event:MouseEvent):void
{
// addPerson按钮处理
this.remoteObject.addPerson(this.person);
}
protected function btnShowPerson_clickHandler(event:MouseEvent):void
{
// showPerson按钮处理
this.remoteObject.getPerson();
}
protected function remoteObject_faultHandler(event:FaultEvent):void
{
// 远程服务调用失败处理
Alert.show("远程服务调用失败!\n"+event.message);
}
protected function method1_resultHandler(event:ResultEvent):void
{
// 调用addPerson方法,提示添加成功
Alert.show("添加成功!\n");
}
protected function method2_resultHandler(event:ResultEvent):void
{
// 调用getPerson方法,返回结果处理
listPerson = event.result as ArrayCollection;
Alert.show(listPerson.toString());
}
protected function method3_resultHandler(event:ResultEvent):void
{
// 调用sayHello方法,返回结果处理
var name:String=event.result as String;
Alert.show(name);
}
protected function button2_clickHandler(event:MouseEvent):void
{
// 说话按钮
remoteObject.sayHello(txtName.text);
}
]]>
</fx:Script>
<fx:Binding source="names.text" destination="person.name" twoWay="true"/>
<fx:Binding source="sex.text" destination="person.sex" twoWay="true"/>
<fx:Binding source="age.text" destination="person.age" twoWay="true"/>
<fx:Binding source="address.text" destination="person.address" twoWay="true"/>
<s:Panel width="398" height="221" title="Person" left="10" top="10">
<s:Button x="60" label="addPerson" bottom="10" id="addPerson" click="btnPerson_clickHandler(event)"/>
<s:Label x="13" y="16" text="Name:"/>
<s:Label x="13" y="50" text="Sex:"/>
<s:Label x="13" y="83" text="Age:"/>
<s:Label x="10" y="123" text="Address:"/>
<s:TextInput x="60" y="13" width="300" id="names"/>
<s:TextInput x="60" y="47" width="300" id="sex"/>
<s:TextInput x="60" y="80" width="300" id="age"/>
<s:TextInput x="60" y="116" width="300" id="address"/>
</s:Panel>
<s:Button x="287" y="250" label="发送" click="button2_clickHandler(event)"/>
<s:TextInput x="151" y="249" id="txtName"/>
<s:Label x="10" y="256" text="添加你想说的内容:" fontSize="15" fontWeight="bold" fontFamily="中易黑体"/>
<s:Panel y="290" left="10" width="528" height="227" title="Person2">
<mx:DataGrid x="10" y="10" bottom="30" left="5" right="5" top="5" id="grid" dataProvider="{this.listPerson}">
<mx:columns>
<mx:DataGridColumn headerText="Name" dataField="name"/>
<mx:DataGridColumn headerText="Sex" dataField="sex"/>
<mx:DataGridColumn headerText="Age" dataField="age"/>
<mx:DataGridColumn headerText="Address" dataField="address"/>
</mx:columns>
</mx:DataGrid>
<s:Button x="0" y="163" label="showPerson" left="5" bottom="5" click="btnShowPerson_clickHandler(event)"/>
</s:Panel>
</s:Application>
2)添加对象
package cn.java.model
{
[RemoteClass(alias="cn.java.model.Person")]
[Bindable]
public class Person
{
public var name:String;
public var sex:String;
public var age:String;
public var address:String;
public function Person()
{
}
}
}
运行F11进行查看,可实现用户添加及显示