Parsley框架之Hello World

Daniel Yang 撰写  

parsley_logo
(替阿银开个头。写一个Hello world示例.)

Parsley是Flex/Flash/AIR的一个开发框架,使用AS3。
Spicelib是一个AS3的库,Parsley基于这个库,但是可以单独使用。


Parsley的功能有:

  • Flexible IOC Container: Supports configuration with AS3 Metadata, MXML, XML files, ActionScript
  • Dependency Injection: Injection by type or id – for constructors, methods or properties
  • Messaging Framework: Fully decoupled senders and receivers, can serve as a basis for MVC architectures
  • Flex View Wiring: Easily wire Flex components to objects declared in the container
  • Advanced container features: Asynchronously initializing objects, object lifecycle, modular configuration contexts
  • Integration with Flex Modules: Allows configuration to be loaded and unloaded alongside Flex Modules
  • Localization: Integrates with Flex ResourceManager for Flex Applications, contains its own Localization Framework for Flash Applications
  • Extensibility: Easily create your own configuration tags, a single implementation can be used as AS3 Metadata, MXML or XML tag
  • And much more…bla bla blah

Spicelib同时也提供:

  • Reflection API: A clean object-oriented API built around the describeType XML output
  • XML-to-Object Mapper: Flexible architecture for mapping from XML to AS3 classes – in both directions
  • Task Framework: Abstraction for asynchronous operations and sequential or concurrent execution
  • Logging: Logging Framework for Flash Applications

Step 1, 下载

http://www.spicefactory.org/parsley/download.php

Step 2, 建立Flex项目

这个大家都会。在Flex Builder 3中建立一个ParsleyTest的项目。

我们在这个项目中,完成一个用户登录的示例。

Step 3, 引用

解压后,会有3个文件夹:

lib下,是你在开发的时候可能会用到的几个swc库文件。

src下,不言而喻。

release下,是我们这个教程需要的东西。当然,不是全部,我们这里只用到parsley-complete-flex-2.0.1.swc, spicelib-complete-flex-2.0.1.swc
官方说只用一个就可以了–那是不可能的。
为了方便,我们把这个文件移至ParsleyTest项目的lib文件夹下。

Step3, 建立Service

当然,一个Flex程序,应该是有服务端的。我们通过这个Service层来访问服务端。

首先要对这个Service抽象一下,这也是写在Parsley的BP中的。我们对服务端的业务访问都是由它来代理的。

代码很简单:

package org.cnflex.parsleytest.service
{
    public interface ILoginService
    {
        function login(user:String, passwd:String):void;
    }
}

代码不动,接口先行。现在实现这个接口:

package org.cnflex.parsleytest.service
{
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;

public class LoginServiceImpl extends EventDispatcher implements ILoginService
{
public function LoginServiceImpl(target:IEventDispatcher=null)
{
super(target);
}

public function login(user:String, passwd:String):void
{
//这里要访问服务器。
}

}
}

要注意的是,需要把服务从EventDispatcher继承,这样LoginServiceImpl就可以dispatchEvent了,比如,登录成功,失败,网络异常等事件。
我们先不管login代码里怎么访问服务器。先看看在界面上怎么来调用这个LoginServiceImpl。
这就要使用到Parsley的两个重要功能:Injection,IOC。
这些概念都是从spring framework或者相似的框架中来的。

需要一个配置文件来完成这个,Parsley支持mxml,xml格式,也支持多重配置文件。
现在我们用mxml方式。建立一个mxml配置,为了方便,直接放置于src目录下。

题外:如何建立一个从Object继承的组件。

parsley_beans

我们在这个配置中先声明一个RemoteObject,访问服务端全靠它了。

然后再把刚才声明的服务放在这个配置里,把RemoteObject注入到服务中。代码大概为:

<?xml version="1.0" encoding="utf-8"?>
<mx:Object xmlns="*" xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:service="org.cnflex.parsleytest.service.*">
<mx:RemoteObject id="authRO" showBusyCursor="true" endpoint="http://localhost:8000/amf" destination="auth"/>
<service:LoginServiceImpl id="loginService"/>
</mx:Object>

这样,所有在项目里标注Inject标签的变量,都会从这里找。刚才说了,我们希望登录成功,失败等事件从这里发出,那就用Parsley标签来声明一下。
声明事件先:

package org.cnflex.parsleytest.event
{
import flash.events.Event;

public class LoginEvent extends Event
{
public function LoginEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}

public static const LOGINSUCCESS:String = "loginSuccess";
public static const LOGINFAIL:String = "loginFail";

}
}

刚才的LoginServiceImpl就变成了:

package org.cnflex.parsleytest.service
{
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;

[ManagedEvents("loginSuccess,loginFail")]
public class LoginServiceImpl extends EventDispatcher implements ILoginService
{
[Inject(id="authRO")]
public var service:RemoteObject;

public function LoginServiceImpl(target:IEventDispatcher=null)
{
super(target);
}

public function login(user:String, passwd:String):void
{
//这里要访问服务器。
}

}
}

我们特意在Inject标签中说明id,就是想找配置文件中的那个相同id的RemoteObject对象。
注意:这个变量是public的,要不然Parsley也访问不到哦~

现在我们有了一切,可以访问服务端了,我们需要用AsyncToken:

public function login(user:String, passwd:String):void{
    var token:AsyncToken = service.login(user, passwd);
    token.addResponder(new AsyncResponder(onLogin, onFault, token));
}

//如果登录成功了, 就用事件的方式告诉界面,或者其他需要知道的地方。
//一些服务端返回的数据也可以在这里带入
protected function onLogin(event:ResultEvent, token:AsyncToken):void{
    var evt:LoginEvent = new LoginEvent(LoginEvent.LOGINSUCCESS);
    this.dispatchEvent(evt);
}

//自己实现onFault.

如何知道已经登录成功,失败了呢?我们在主程序上试试:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

<mx:Script>
<![CDATA[
import org.cnflex.parsleytest.event.LoginEvent;

[MessageHandler(selector="loginSuccess")]
public function onLoginSuc(evt:LoginEvent):void{
//登录后干点啥。。。
}

]]>
</mx:Script>

</mx:Application>

一个MessageHandler就能解决问题,方便吧?

注意:这个方法是public的,要不然Parsley也访问不到哦~

那,我们怎么登录呢?界面上如何调用我们刚才写的一堆的代码?
答案还是Inject。还记得我们在配置中声明了一个LoginServiceImpl吧,把它拿过来:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

<mx:Script>
<![CDATA[
import org.cnflex.parsleytest.event.LoginEvent;

import org.cnflex.parsleytest.service.ILoginService;

[Inject(id="loginService")]
public var service:ILoginService;

private function onLoginClick():void{
this.service.login('d_yang','******');
}

[MessageHandler(selector="loginSuccess")]
public function onLoginSuc(evt:LoginEvent):void{
//登录后干点啥。。。
}

]]>
</mx:Script>
<mx:Button label="假的登录" click="onLoginClick()"/>
</mx:Application>

好了。大功告成。运行。

但是却不会执行……为啥?

因为缺少了最重要的一步:初始化Parsley:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
preinitialize="FlexContextBuilder.build(Beans)"
addedToStage="dispatchEvent(new Event('configureIOC', true));">

<mx:Script>
<![CDATA[
import org.cnflex.parsleytest.event.LoginEvent;
import org.spicefactory.parsley.flex.FlexContextBuilder;
import org.cnflex.parsleytest.service.ILoginService;

[Inject(id="loginService")]
public var service:ILoginService;

private function onLoginClick():void{
this.service.login('d_yang','******');
}

[MessageHandler(selector="loginSuccess")]
public function onLoginSuc(evt:LoginEvent):void{
//登录后干点啥。。。
}

]]>
</mx:Script>
<mx:Button label="假的登录" click="onLoginClick()"/>
</mx:Application>

注意:这两个事件是不能改的。Parsley要求的很少,这点还是可以原谅的。

还有一个BP:细心的兄弟可能会发现,我在主程序中声明的是“public var service:ILoginService”,而不是具体的实现。
其中原因留给兄弟们思考吧。

这个教程到此为止。

兄弟们可以继续了解:

  • 配置文件
  • 注入
  • Action的用法
  • 模块的支持
  • 等等等等。

Parsley的确是我目前所见过的用着最舒服的框架。

希望这篇文章能够给大家伙帮点忙。

代码打包附上,可以直接导入Flex Builder。

http://blog.ityao.com/wp-content/uploads/2009/09/ParsleyTest.zip

感谢大家对IT妖的支持。

期待妖人们的加入。


9 条评论

  1. 发表了 2009年09月11日 在 9:52 上午 | 永久链接 |

    不错,很仔细,例子能独立运行,很有think in XXXX系列的风范

  2. Daniel Yang
    发表了 2009年09月11日 在 10:01 上午 | 永久链接 |

    “Think in OOXX”?

  3. Daniel Yang
    发表了 2009年09月11日 在 10:02 上午 | 永久链接 |

    想起来了,Think in XXXX的风范就是:贴代码

    • 发表了 2009年09月11日 在 10:14 上午 | 永久链接 |

      还有的就是代码都是可以粘贴出来就独立运行的,这点对初学者很重要:)

  4. Daniel Yang
    发表了 2009年09月11日 在 10:19 上午 | 永久链接 |

    我尽可能保证把。不过在文中的一般都是片段。

  5. 发表了 2009年09月12日 在 12:45 上午 | 永久链接 |

    不错,写得很详细,也很易于理解…

    顺便问下,一般你们编辑都是直接在后台直接编辑的?能否支持使用Windows live writer来写文章?

  6. 发表了 2009年09月12日 在 9:34 上午 | 永久链接 |

    不错,学习了

  7. 唐滨
    发表了 2010年02月1日 在 12:03 下午 | 永久链接 |

    不错,欢迎大家继续分析使用心得哈!

个引用通告

  1. IOC(DI) in Flex – IT妖怪 发表在 2009年12月10日 于 10:58 下午

    [...] Parsley(由PowerFlasher开发,个人比较喜欢这个框架,本站前面由Daniel也写了一篇Parsley的入门文章,很不错~~~严格意义上来说它不算一种MVC框架,属于一套Toolkit,你完全可以使用自己的MVC方式来组织) [...]

发表评论

你必须在 登录 后才能发表评论.