`
it_liuyong
  • 浏览: 97998 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用 Parsley 框架构建 Flex 应用程序 .

    博客分类:
  • flex
 
阅读更多
使用 Parsley 框架构建 Flex 应用程序 .
2009-08-10 17:35 1681人阅读 评论(0) 收藏 举报
在最近研究了“Swiz”和“Spring ActionScript”(1、2、3)之后,我决定在新的 Parsley 框架版本中试验一下,构建 inSync(简单的 Contact Management 应用程序,我经常用于试验和演示 Flex 和 Adobe AIR 中的不同特性和技术)的 Parsley 版本。



Parsley 最初是一个依赖注入(Dependency Injection)框架。它还提供了一个非常有趣的消息传递基础结构。我不打算在此详细介绍依赖性注入:以前的 Swiz 和 Spring ActionScript 文章提供了一些背景信息,还详细列出了许多资源。
如果您只想运行应用程序并深入研究代码,可以访问以下链接:
单击此处运行应用程序。
单击此处查看源代码。
对象配置
Parsley 支持使用 MXML(比如 Swiz)、XML(比如 Spring ActionScript)、ActionScript 或者任意组合这些方法来配置应用程序的核心对象。可以扩展该框架并创建自己的配置机制。
对于 inSync 应用程序,我使用了一个简单的 MXML 配置(Config.mxml),其定义如下:


[cpp] view plaincopyprint?
01.<?xml version="1.0" encoding="utf-8"?> 
02.<Object xmlns="*" xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:services="insync.parsley.services.*"> 
03.  
04.    <mx:RemoteObject 
05.            id="contactRO" 
06.            destination="contacts" 
07.            endpoint="http://localhost:8400/samples/messagebroker/amf" 
08.            showBusyCursor="true" /> 
09.  
10.    <services:ContactService /> 
11.  
12.</Object> 
<?xml version="1.0" encoding="utf-8"?>
<Object xmlns="*" xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:services="insync.parsley.services.*">

    <mx:RemoteObject
            id="contactRO"
            destination="contacts"
            endpoint="http://localhost:8400/samples/messagebroker/amf"
            showBusyCursor="true" />

    <services:ContactService />

</Object>

注意:在实际的应用程序中,您可能不希望在源代码中硬编码服务的端点。可以使用 XML 配置选项以更加“具体化”的形式配置端点。单击此处了解关于此主题的更多信息。
框架初始化
使用对应于所选配置方法的 ContextBuilder 类来初始化 Parsley 框架。下面是 inSync 应用程序的主应用程序文件。Parsley 在应用程序的 preinitialize 事件中初始化。

[cpp] view plaincopyprint?
01.<?xml version="1.0" encoding="utf-8"?> 
02.<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:views="insync.parsley.views.*" 
03.   paddingTop="0" paddingLeft="0" paddingRight="0" paddingBottom="0" 
04.   preinitialize="FlexContextBuilder.build(Config)"> 
05.  
06.    <mx:Script> 
07.       <!--[CDATA[ 
08.           import org.spicefactory.parsley.flex.FlexContextBuilder; 
09.       ]]--> 
10.   </mx:Script> 
11.  
12.    <mx:Style source="styles.css" /> 
13.  
14.    <views:MainView /> 
15.  
16.</mx:Application>  
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:views="insync.parsley.views.*"
   paddingTop="0" paddingLeft="0" paddingRight="0" paddingBottom="0"
   preinitialize="FlexContextBuilder.build(Config)">

    <mx:Script>
       <!--[CDATA[
           import org.spicefactory.parsley.flex.FlexContextBuilder;
       ]]-->
   </mx:Script>

    <mx:Style source="styles.css" />

    <views:MainView />

</mx:Application>

依赖注入
Parsley 支持构造函数注入、方法注入和属性注入(根据类型或 id 进行注入)。
在下面的例子(ContactForm.mxml)中,框架将注入 IContactService 接口的一个特定实现。在本例中,将注入在 Config.mxml 中创建的 ContactService 实例。这是一个按类型注入的示例。对接口进行编码可以将视图从特定的 IContactService 实现中解耦出来。
注意:Parsley 不会强迫您使用任何特定的设计模式。为了简单起见,在本示例应用程序中,我将一个服务直接注入到视图中。使用接口可以提供一定的解耦级别,但是您也可以使用其他模式(比如 Presentation Model)来获得更高的抽象级别。Parsley  的依赖注入(Dependency Injection)和消息传递(Messaging)基础结构使这些模式的实现更加简单。

[c-sharp] view plaincopyprint?
01.<?xml version="1.0" encoding="utf-8"?> 
02.<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" 
03.   addedToStage="dispatchEvent(new Event('configureIOC', true))"> 
04.  
05.    <mx:Script> 
06.       <!--[CDATA[ 
07.  
08.       import insync.parsley.model.Contact; 
09.       import insync.parsley.services.IContactService; 
10.  
11.       [Inject] 
12.       public var service:IContactService; 
13.  
14.       [Bindable] 
15.       public var contact:Contact; 
16.  
17.       private function save():void 
18.       { 
19.           contact.firstName = firstName.text; 
20.           contact.lastName = lastName.text; 
21.           contact.email = email.text; 
22.           service.save(contact); 
23.       } 
24.  
25.       private function remove():void 
26.       { 
27.           service.remove(contact);        
28.       } 
29.  
30.       ]]--> 
31.   </mx:Script> 
32.  
33.    <mx:Form> 
34.        <mx:FormItem label="Id"> 
35.            <mx:TextInput text="{contact.id}" enabled="false"/> 
36.        </mx:FormItem> 
37.        <mx:FormItem label="First Name"> 
38.            <mx:TextInput id="firstName" text="{contact.firstName}"/> 
39.        </mx:FormItem> 
40.        <mx:FormItem label="Last Name"> 
41.            <mx:TextInput id="lastName" text="{contact.lastName}"/> 
42.        </mx:FormItem> 
43.        <mx:FormItem label="Email"> 
44.            <mx:TextInput id="email" text="{contact.email}"/> 
45.        </mx:FormItem> 
46.    </mx:Form> 
47.  
48.    <mx:HBox left="12" bottom="12"> 
49.        <mx:Button label="Save" click="save()"/> 
50.        <mx:Button label="Delete" click="remove()"/> 
51.    </mx:HBox> 
52.  
53.</mx:Canvas> 
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
   addedToStage="dispatchEvent(new Event('configureIOC', true))">

    <mx:Script>
       <!--[CDATA[

       import insync.parsley.model.Contact;
       import insync.parsley.services.IContactService;

       [Inject]
       public var service:IContactService;

       [Bindable]
       public var contact:Contact;

       private function save():void
       {
           contact.firstName = firstName.text;
           contact.lastName = lastName.text;
           contact.email = email.text;
           service.save(contact);
       }

       private function remove():void
       {
           service.remove(contact);      
       }

       ]]-->
   </mx:Script>

    <mx:Form>
        <mx:FormItem label="Id">
            <mx:TextInput text="{contact.id}" enabled="false"/>
        </mx:FormItem>
        <mx:FormItem label="First Name">
            <mx:TextInput id="firstName" text="{contact.firstName}"/>
        </mx:FormItem>
        <mx:FormItem label="Last Name">
            <mx:TextInput id="lastName" text="{contact.lastName}"/>
        </mx:FormItem>
        <mx:FormItem label="Email">
            <mx:TextInput id="email" text="{contact.email}"/>
        </mx:FormItem>
    </mx:Form>

    <mx:HBox left="12" bottom="12">
        <mx:Button label="Save" click="save()"/>
        <mx:Button label="Delete" click="remove()"/>
    </mx:HBox>

</mx:Canvas>

注意,为了在将视图添加到舞台上时注入其依赖性,视图必须分派“configureIOC”事件。
消息传递
Parsley 提供了一种通用消息传递基础结构,支持以一种解耦的、灵活且易用的方式在对象之间交换消息:
事件分派程序和时间处理程序彼此互不了解。
事件分派程序和事件处理程序已从框架中解耦出来:可以以 Flex 的方式分派事件。
作为一个示例,我们看一下 inSync 中的搜索特性:
Toolbar 类包含一个简单的 TextInput,支持用户指定一个搜索条件。
ContactList 类在一个 DataGrid 中显示搜索结果。
Toolbar 类定义如下(为了保持条理清晰,已删除不重要的代码):

[c-sharp] view plaincopyprint?
01.<?xml version="1.0" encoding="utf-8"?> 
02.<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" 
03.   addedToStage="dispatchEvent(new Event('configureIOC', true))"> 
04.  
05.    <mx:Metadata> 
06.        [ManagedEvents("search")] 
07.    </mx:Metadata> 
08.  
09.    <mx:Script> 
10.       <!--[CDATA[ 
11.           import insync.parsley.events.SearchEvent; 
12.       ]]--> 
13.   </mx:Script> 
14.  
15.    <mx:Label text="Search:" top="18" right="164"/> 
16.  
17.    <mx:TextInput id="searchBox" right="0" top="16" 
18.       change="dispatchEvent(new SearchEvent(SearchEvent.SEARCH, searchBox.text))"/> 
19.  
20.</mx:Canvas> 
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%"
   addedToStage="dispatchEvent(new Event('configureIOC', true))">

    <mx:Metadata>
        [ManagedEvents("search")]
    </mx:Metadata>

    <mx:Script>
       <!--[CDATA[
           import insync.parsley.events.SearchEvent;
       ]]-->
   </mx:Script>

    <mx:Label text="Search:" top="18" right="164"/>

    <mx:TextInput id="searchBox" right="0" top="16"
       change="dispatchEvent(new SearchEvent(SearchEvent.SEARCH, searchBox.text))"/>

</mx:Canvas>

注意,它在搜索输入字段的内容发生变化时分派一个 SearchEvent 事件。
该事件被定义为一个托管事件(使用 ManagedEvents 注释),表示框架将确保关注该事件的所有实体都会收到该事件。
如何注册托管事件的监听器呢?只需使用 [MessageHandler] 注释一个函数,无论显示对象层次结构如何,或者无论事件是否浮升(bubble),该函数都会自动成为该事件的事件处理程序。
下面展示了如何在 ContactList 中注册监听器(为了保持条理清晰,已删除不重要的代码):

[c-sharp] view plaincopyprint?
01.<?xml version="1.0" encoding="utf-8"?> 
02.<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%" 
03.   addedToStage="dispatchEvent(new Event('configureIOC', true))"> 
04.  
05.    <mx:Script> 
06.       <!--[CDATA[ 
07.  
08.           import mx.controls.Alert; 
09.           import mx.collections.ArrayCollection; 
10.           import mx.rpc.events.FaultEvent; 
11.           import mx.rpc.AsyncToken; 
12.           import mx.rpc.AsyncResponder; 
13.           import mx.rpc.events.ResultEvent; 
14.  
15.           import insync.parsley.events.SearchEvent; 
16.           import insync.parsley.services.IContactService;         
17.  
18.           [Inject] 
19.           [Bindable] 
20.           public var service:IContactService; 
21.  
22.           [Bindable] 
23.           public var contacts:ArrayCollection; 
24.  
25.           [MessageHandler] 
26.           public function searchHanlder(event:SearchEvent):void 
27.           { 
28.               service.getContactsByName(searchStr).addResponder(new AsyncResponder(getContacts_result, faultHandler)); 
29.           } 
30.  
31.           private function getContacts_result(event:ResultEvent, token:AsyncToken):void 
32.           { 
33.               contacts = event.result as ArrayCollection; 
34.           }   
35.  
36.           private function faultHandler(event:FaultEvent):void 
37.           { 
38.               Alert.show(event.fault.faultString); 
39.           }       
40.  
41.       ]]--> 
42.   </mx:Script> 
43.  
44.    <mx:DataGrid id="dg" dataProvider="{contacts}" width="100%" top="0" left="0" right="0" bottom="0"/> 
45.  
46.</mx:Canvas> 
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%"
   addedToStage="dispatchEvent(new Event('configureIOC', true))">

    <mx:Script>
       <!--[CDATA[

           import mx.controls.Alert;
           import mx.collections.ArrayCollection;
           import mx.rpc.events.FaultEvent;
           import mx.rpc.AsyncToken;
           import mx.rpc.AsyncResponder;
           import mx.rpc.events.ResultEvent;

           import insync.parsley.events.SearchEvent;
           import insync.parsley.services.IContactService;       

           [Inject]
           [Bindable]
           public var service:IContactService;

           [Bindable]
           public var contacts:ArrayCollection;

           [MessageHandler]
           public function searchHanlder(event:SearchEvent):void
           {
               service.getContactsByName(searchStr).addResponder(new AsyncResponder(getContacts_result, faultHandler));
           }

           private function getContacts_result(event:ResultEvent, token:AsyncToken):void
           {
               contacts = event.result as ArrayCollection;
           } 

           private function faultHandler(event:FaultEvent):void
           {
               Alert.show(event.fault.faultString);
           }     

       ]]-->
   </mx:Script>

    <mx:DataGrid id="dg" dataProvider="{contacts}" width="100%" top="0" left="0" right="0" bottom="0"/>

</mx:Canvas>

借助简单的 [MessageHandler] 注释,每次在应用程序中分派函数参数的数据类型时都将调用该处理程序。如果您需要更严格的控制,可以使用选择器符号来指定事件类型。例如,在 MainView.mxml 中,我们将 contactDeleted 函数注册为 ContactEvent.DELETED 事件的一个处理程序,如下所示。

[c-sharp] view plaincopyprint?
01.[MessageHandler(selector="contactDeleted")] 
02.public function contactDeletedHandler(event:ContactEvent):void 
03.{ 
04.}    
[MessageHandler(selector="contactDeleted")]
public function contactDeletedHandler(event:ContactEvent):void
{
}

Parsley 框架还有更多消息传递功能。例如,可以使用 [MessageBinding] 将一个对象的属性绑定到一个事件的对应属性。

[c-sharp] view plaincopyprint?
01.[MessageBinding(messageProperty="result",type=" mx.rpc.events.ResultEvent")]  
02.public var contacts:ArrayCollection;     
[MessageBinding(messageProperty="result",type=" mx.rpc.events.ResultEvent")]
public var contacts:ArrayCollection;

安装说明
1 从此处下载项目
2 将其导入 Flex Builder
3 运行应用程序。应用程序默认配置为使用 MockService (ContactServiceMock),所以它运行时不需要任何后端。
如果希望使用 Remoting service 代替 MockService:
4 将 Config.mxml 中的 <services:ContactServiceMock/> 替换为 <services:ContactServiceRemote/>
5 安装功能全面的 BlazeDS 服务器。
6 下载 insync-parsley-java.zip 并将其解压到本地文件系统中。
7将 classes/insync 复制到 blazeds/tomcat/webapps/samples/WEB-INF/classes/insync 文件夹中。
8 将以下目标添加到 blazeds/tomcat/webapps/samples/WEB-INF/flex/remoting-config.xml 文件中:


[c-sharp] view plaincopyprint?
01.<destination id="contacts"> 
02.        <properties> 
03.            <source>insync.dao.ContactDAO</source> 
04.            <scope>application</scope> 
05.        </properties> 
06.</destination> 
<destination id="contacts">
        <properties>
            <source>insync.dao.ContactDAO</source>
            <scope>application</scope>
        </properties>
</destination>

9 将 insync/sampledb/insync 复制到 blazeds/sampledb/insync 文件夹中
10 编辑 blazeds/sampledb 文件夹中的 server.properties,修改文件(如下所示),将 insync 数据库添加到启动步骤中。

[c-sharp] view plaincopyprint?
01.server.database.0=file:flexdemodb/flexdemodb 
02.server.dbname.0=flexdemodb 
03.server.database.1=file:insync/insync 
04.server.dbname.1=insync 
05.server.port=9002 
06.server.silent=true 
07.server.trace=false   
server.database.0=file:flexdemodb/flexdemodb
server.dbname.0=flexdemodb
server.database.1=file:insync/insync
server.dbname.1=insync
server.port=9002
server.silent=true
server.trace=false

11 启动数据库(startdb.bat 或 startdb.sh)
12 启动 BlazeDS
13 运行应用程序

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics