Cairngorm示例:用户登录
1. Cairngorm简介
Cairngorm是一个Flex程序开发框架,基于MVC设计模式。
使用Cairngorm进行开发时我们一般涉及以下几个部件的开发:
ModelLocator:定义Model。ActionScript类,一般采用singleton模式实现,必须
是Bindable的
ServiceLocator:定义与之进行通讯的服务器端的服务。MXML Component
Event:继承CairngormEvent
Command:处理Event的逻辑。实现ICommand接口
Controller:注册Event与Command之间的对应关系。继承FrontController
Delegate:服务器端服务的代理。ActionScript类
以用户输入数据、点击确定按钮,客户端与服务器通讯,然后根据处理结果进行相应操
作这一典型的处理过程为例,确定按钮事件中,用户数据被附加到Event上然后发布,
Cairngorm根据Controller中注册的信息,找到处理该Event的Command,该Command通过
ServiceLocator获得相应的远程服务,从Event中提取用户数据发送到远程服务,响应回
来后,Command根据响应数据,通过ModelLocator修改数据,由于ModelLocator和页面数
据是Bind在一起的,所以也就相应地修改了画面的显示。
2. 示例
以下是用户输入ID、password进行登录的示例代码,当ID、password都是“test”的时候,
登录成功,画面转到有主菜单的画面。
服务器端简单地实现了一个服务,代码如下:
Java代码
1. public class UserService {
2. public boolean isValid(String username, String password) {
3. if ("test".equals(username) && "test".equals(password)) {
4. return true;
5. } else {
6. return false;
7. }
8. }
9. }
public class UserService {
public boolean isValid(String username, String password) {
if ("test".equals(username) && "test".equals(password)) {
return true;
} else {
return false;
}
}
}
客户端代码的包结构如下(其中方括弧表示包),其中没有使用Delegate:
login.mxml
[business]
Controller.as
Services.mxml
[commands]
LoginCommand.as
[events]
LoginEvent.as
[model]
ModelLocator.as
ModelLocator代码如下:
Java代码
1. package model
2. {
3. [Bindable]
4. public class ModelLocator
5. {
6. static private var _instance : ModelLocator = null;
7.
8. public var showLoginPanel : Boolean = true;
9. public var currentState : String = "";
10.
11. static public function getInstance() : ModelLocator
12. {
13. if (_instance == null) {
14. _instance = new ModelLocator();
15. }
16. return _instance;
17. }
18. }
19. }
package model
{
[Bindable]
public class ModelLocator
{
static private var _instance : ModelLocator = null;
public var showLoginPanel : Boolean = true;
public var currentState : String = "";
static public function getInstance() : ModelLocator
{
if (_instance == null) {
_instance = new ModelLocator();
}
return _instance;
}
}
}
ServiceLocator代码如下:
Xml代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <rds:ServiceLocator xmlns:rds="com.adobe.cairngorm.business.*"
3. xmlns:mx="http://www.adobe.com/2006/mxml">
4. <mx:RemoteObject
5. id="userService"
6. destination="userServiceDestination"
7. endpoint="http://localhost:8080/test-server/messagebroker/amf">
8. </mx:RemoteObject>
9. </rds:ServiceLocator>
<?xml version="1.0" encoding="utf-8"?>
<rds:ServiceLocator xmlns:rds="com.adobe.cairngorm.business.*"
xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:RemoteObject
id="userService"
destination="userServiceDestination"
endpoint="http://localhost:8080/test-server/messagebroker/amf">
</mx:RemoteObject>
</rds:ServiceLocator>
Event代码如下:
Java代码
1. package business.events
2. {
3. import com.adobe.cairngorm.control.CairngormEvent;
4.
5. public class LoginEvent extends CairngormEvent
6. {
7. static public var EVENT_ID:String="login";
8. public var username : String = null;
9. public var password : String = null;
10.
11. public function LoginEvent()
12. {
13. super(EVENT_ID);
14. }
15. }
16. }
package business.events
{
import com.adobe.cairngorm.control.CairngormEvent;
public class LoginEvent extends CairngormEvent
{
static public var EVENT_ID:String="login";
public var username : String = null;
public var password : String = null;
public function LoginEvent()
{
super(EVENT_ID);
}
}
}
Command代码如下:
Java代码
1. package business.commands
2. {
3. import com.adobe.cairngorm.business.ServiceLocator;
4. import com.adobe.cairngorm.commands.ICommand;
5. import com.adobe.cairngorm.control.CairngormEvent;
6.
7. import mx.rpc.events.ResultEvent;
8. import mx.rpc.remoting.RemoteObject;
9.
10. import model.ModelLocator;
11. import business.events.LoginEvent;
12.
13. public class LoginCommand implements ICommand
14. {
15. private var _modelLoc : ModelLocator = ModelLocator.getInstance();
16. private var _serviceLoc : ServiceLocator = ServiceLocator.getInstance();
17.
18. public function execute(event:CairngormEvent):void
19. {
20. var loginEvent : LoginEvent = LoginEvent(event);
21. var userService : RemoteObject = _serviceLoc.getRemoteObject("userService");
22. userService.addEventListener(ResultEvent.RESULT, onResults_login);
23. userService.getOperation("isValid").send(loginEvent.username, loginEvent.password);
24. }
25.
26. private function onResults_login(event:ResultEvent):void
27. {
28. var isValid : Boolean = Boolean(event.result);
29. if (isValid) {
30. _modelLoc.showLoginPanel = false;
31. _modelLoc.currentState = "mainmenu";
32. }
33. }
34. }
35. }
package business.commands
{
import com.adobe.cairngorm.business.ServiceLocator;
import com.adobe.cairngorm.commands.ICommand;
import com.adobe.cairngorm.control.CairngormEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.remoting.RemoteObject;
import model.ModelLocator;
import business.events.LoginEvent;
public class LoginCommand implements ICommand
{
private var _modelLoc : ModelLocator = ModelLocator.getInstance();
private var _serviceLoc : ServiceLocator = ServiceLocator.getInstance();
public function execute(event:CairngormEvent):void
{
var loginEvent : LoginEvent = LoginEvent(event);
var userService : RemoteObject = _serviceLoc.getRemoteObject("userService");
userService.addEventListener(ResultEvent.RESULT, onResults_login);
userService.getOperation("isValid").send(loginEvent.username, loginEvent.password);
}
private function onResults_login(event:ResultEvent):void
{
var isValid : Boolean = Boolean(event.result);
if (isValid) {
_modelLoc.showLoginPanel = false;
_modelLoc.currentState = "mainmenu";
}
}
}
}
Controller代码如下:
Java代码
1. package business
2. {
3. import com.adobe.cairngorm.control.FrontController;
4.
5. import business.events.LoginEvent;
6. import business.commands.LoginCommand;
7.
8. public class Controller extends FrontController
9. {
10. public function Controller()
11. {
12. super();
13. this.addCommand(LoginEvent.EVENT_ID, LoginCommand);
14. }
15. }
16. }
package business
{
import com.adobe.cairngorm.control.FrontController;
import business.events.LoginEvent;
import business.commands.LoginCommand;
public class Controller extends FrontController
{
public function Controller()
{
super();
this.addCommand(LoginEvent.EVENT_ID, LoginCommand);
}
}
}
最后登录画面代码如下
Xml代码
1. <?xml version="1.0" encoding="utf-8"?>
2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
3. width="100%" height="100%" verticalAlign="middle" horizontalAlign="center"
4. fontFamily="Courier New" fontSize="12" currentState="{_model.currentState}">
5. <mx:states>
6. <mx:State name="mainmenu">
7. <mx:RemoveChild target="{panel1}"/>
8. <mx:AddChild position="lastChild">
9. <mx:MenuBar id="mainMenu" width="100%" x="0" y="0" labelField="@label">
10. <mx:XMLList>
11. <menuitem label="数据录入">
12. <menuitem label="顾客信息登记" />
13. <menuitem label="印刷订单录入" />
14. </menuitem>
15. <menuitem label="帮助">
16. <menuitem label="帮助" />
17. <menuitem label="关于" />
18. </menuitem>
19. </mx:XMLList>
20. </mx:MenuBar>
21. </mx:AddChild>
22. <mx:SetProperty name="layout" value="absolute"/>
23. </mx:State>
24. </mx:states>
25. <mx:Panel width="370" height="192" layout="absolute" title="登録" id="panel1" visible="{_model.showLoginPanel}">
26. <mx:Label text="姓 名:" x="44" y="21" width="91"/>
27. <mx:TextInput x="143" y="19" id="txtUsername" maxChars="32"/>
28. <mx:Label x="44" y="51" text="密 码:" width="91"/>
29. <mx:TextInput x="143" y="49" id="txtPassword" maxChars="32" displayAsPassword="true"/>
30. <mx:Button x="70" y="118" label="登录" id="btnLogin" click="btnLogin_clicked()" width="92"/>
31. <mx:Button x="170" y="118" label="重置" id="btnReset" click="btnReset_clicked()" width="92"/>
32. </mx:Panel>
33.
34.
35.
36. <mx:Script>
37. <![CDATA[
38. import model.ModelLocator;
39. import business.events.LoginEvent;
40.
41. [Bindable]
42. private var _model:ModelLocator=ModelLocator.getInstance();
43.
44. private function btnLogin_clicked() : void
45. {
46. var event : LoginEvent = new LoginEvent();
47. event.username = txtUsername.text;
48. event.password = txtPassword.text;
49. event.dispatch();
50. }
51.
52. private function btnReset_clicked() : void
53. {
54. //略
55. }
56. ]]>
57. </mx:Script>
58.
59. <rds:Services xmlns:rds="business.*"/>
60.
61. <router:Controller xmlns:router="business.*"/>
62.
63. </mx:Application>
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%" height="100%" verticalAlign="middle" horizontalAlign="center"
fontFamily="Courier New" fontSize="12" currentState="{_model.currentState}">
<mx:states>
<mx:State name="mainmenu">
<mx:RemoveChild target="{panel1}"/>
<mx:AddChild position="lastChild">
<mx:MenuBar id="mainMenu" width="100%" x="0" y="0" labelField="@label">
<mx:XMLList>
<menuitem label="数据录入">
<menuitem label="顾客信息登记" />
<menuitem label="印刷订单录入" />
</menuitem>
<menuitem label="帮助">
<menuitem label="帮助" />
<menuitem label="关于" />
</menuitem>
</mx:XMLList>
</mx:MenuBar>
</mx:AddChild>
<mx:SetProperty name="layout" value="absolute"/>
</mx:State>
</mx:states>
<mx:Panel width="370" height="192" layout="absolute" title="登録" id="panel1" visible="{_model.showLoginPanel}">
<mx:Label text="姓 名:" x="44" y="21" width="91"/>
<mx:TextInput x="143" y="19" id="txtUsername" maxChars="32"/>
<mx:Label x="44" y="51" text="密 码:" width="91"/>
<mx:TextInput x="143" y="49" id="txtPassword" maxChars="32" displayAsPassword="true"/>
<mx:Button x="70" y="118" label="登录" id="btnLogin" click="btnLogin_clicked()" width="92"/>
<mx:Button x="170" y="118" label="重置" id="btnReset" click="btnReset_clicked()" width="92"/>
</mx:Panel>
<mx:Script>
<![CDATA[
import model.ModelLocator;
import business.events.LoginEvent;
[Bindable]
private var _model:ModelLocator=ModelLocator.getInstance();
private function btnLogin_clicked() : void
{
var event : LoginEvent = new LoginEvent();
event.username = txtUsername.text;
event.password = txtPassword.text;
event.dispatch();
}
private function btnReset_clicked() : void
{
//略
}
]]>
</mx:Script>
<rds:Services xmlns:rds="business.*"/>
<router:Controller xmlns:router="business.*"/>
</mx:Application>
其中需要注意的是Application的currentState和登录窗口的visible属性是bind到ModelLocator的。
website:http://www.iteye.com/topic/599640