加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Flex 4.1 + BlazeDS框架 + Cairngorm框架(Demo实例)

发布时间:2020-12-15 03:45:06 所属栏目:百科 来源:网络整理
导读:Cairngorm 的各个部分: ModelLocator:在一个地方存储程序中所有的值对象(ValueObjects,数据)并共享变量。它与HTTP Session对象相类似,不过它存储在Flex客户端,而不是存储在一个中间层程序服务器的服务器端。 View(视图):一个或多个Flex组件(Button

Cairngorm的各个部分:

  1. ModelLocator:在一个地方存储程序中所有的值对象(ValueObjects,数据)并共享变量。它与HTTP Session对象相类似,不过它存储在Flex客户端,而不是存储在一个中间层程序服务器的服务器端。
  2. View(视图):一个或多个Flex组件(Button,panel,combo Box,Tile等等)绑定到一起形成的一个特定的个体,使用ModelLocator中的数据并且针对用户的交互动作(如点击,鼠标滑过,拖拽等)产生自定义的CairngormEvents。
  3. FrontController(前端控制器):接受CairngormEvents并且将它们映射到CairngormCommands。
  4. Command(命令):处理业务逻辑,调用CairngormDelegates或其他的Commands,以及更新ModelLocator中存储的值对象和变量。
  5. Delegate(委托):由一个Command创建,它将远程过程实例化并且将结果返回给Command。
  6. Service(服务):定义链接到远程数据库的远程过程调用(HTTP,Web Services等)。

Cairngorm的工作流程大体是这样:

客户端界面由View组成的。View使用Flex的binding(绑定)来显示ModelLocator中包含的数据。View根据诸如鼠标点击,按钮按下以及拖拽之类的用户动作产生Event。这些Event被FrontController“广播”并“监听”,FrontController会将Event映射到Command。Command包括业务逻辑,创建所需的Delegate,处理Delegate的响应,以及更新存储在ModelLocator中的数据。由于View是绑定到ModelLocator中的数据上的,所以当ModelLocator中的数据改变的时候View也会自动更新。Delegate调用Service并且将结果提交给Command,这一步是可选的,但是推荐这么做。Service调用远程数据然后将结果提交给Delegate。

Delegate的最简单的形式就是一个中间人的角色。如果一个Command需要调用webservice来获得一些数据,它将创建一个Delegate来完成这个调用。一个Command创建一个Delegate,Delegate调用一个指定的dataService,Service返回结果给Delegate,Delegate返回结果给Command。

Delegate并不是100%必需的,但是当涉及测试&程序环境的时候它们很有帮助。相对于在Command代码中使用查找替换改变所有的引用来测试,将一个Delegate重映射到一个测试Service更为简单。

下面说我的Demo:完成用户登录在后台进行验证合法性,并反馈给前台。

package net.dreamhui.java;

public class LoginUser {
	public UserVO currentUser;
	private String uName;
	private String pWord;

	// Flex端要调用的服务
	
	public UserVO login(UserVO par_user) {
		uName = par_user.userName;
		pWord = par_user.passWord;
		if (uName.equalsIgnoreCase("mazhi") && pWord.equalsIgnoreCase("wwh")) {
			return par_user;
		} else {
			return null;
		}
	}
}
package net.dreamhui.java;

public class UserVO {
	public String userName;
	public String passWord;

	public UserVO() {
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPassWord() {
		return passWord;
	}

	public void setPassWord(String passWord) {
		this.passWord = passWord;
	}
}

对remote-config.xml文件进行配置,加入如下的代码:

<destination id="loginUser">
		<properties>
			<source>net.dreamhui.java.LoginUser</source>
		</properties>
	</destination>
在flashbuilder中新建CairngormDemo的Flex项目并组织目录,如下所示:

各个文件的源代码如下:

CairngormDemo.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"
			   xmlns:business="net.dreamhui.business.*"
			   xmlns:control="net.dreamhui.control.*"
			   xmlns:view="net.dreamhui.view.*"
			   creationComplete="creationComplete()">
	
	<fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;
			import net.dreamhui.model.UserModelLocator;
			
			protected function creationComplete():void
			{
				// UserModelLocator存储程序中的所有值对象
				UserModelLocator.getInstance().addEventListener(UserModelLocator.LOGIN_YES,switchState);
			}
			protected function switchState(event:Event):void
			{
				lgView.currentState = "loginState";
			}
		]]>
	</fx:Script>
	
	<fx:Declarations>
		<!--初始化服务,里面含有Command注册 和 远程过程调用的信息-->
		<business:LoginServiceLocator id="lgService" />
		<control:LoginController id="loginContr" />
		<!--<commands:LoginCommand id="lCommand" />-->
		<!--<model:UserModelLocator id="uLocator" />-->
	</fx:Declarations>
	
	<view:loginView id="lgView" top="10" horizontalCenter="0" width="30%" height="30%" fontSize="20"/>
</s:Application>
LoginView.mxml源码如下:

<?xml version="1.0" encoding="utf-8"?>
<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009"
		 xmlns:s="library://ns.adobe.com/flex/spark"
		 xmlns:mx="library://ns.adobe.com/flex/mx"
		 title="请登陆" currentState="initState"
		 creationComplete="lvcreationComplete(event)">
	<s:states>
		<s:State name="initState"/>
		<s:State name="loginState"/>
	</s:states>
	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.events.FlexEvent;
			import mx.rpc.events.FaultEvent;
			import mx.rpc.events.ResultEvent;
			import mx.validators.Validator;
			import mx.events.ValidationResultEvent;
			import mx.core.UIComponent;
			import net.dreamhui.control.LoginEvent;
			import net.dreamhui.model.UserModelLocator;
			import net.dreamhui.vo.UserVO;
			
			private var validObjs:Array;
			protected function lvcreationComplete(event:FlexEvent):void
			{
				validObjs = [unSV,pwSV]; // 需要进行验证的对象
			}
			protected function submit(event:MouseEvent):void
			{
				var validatorResults:Array;
				validatorResults = Validator.validateAll(validObjs);
				if(validatorResults.length == 0)
				{
					var user:UserVO = new UserVO();
					user.userName = uName.text;
					user.passWord = pWord.text;
					var lgEvent:LoginEvent = new LoginEvent(LoginEvent.LOGIN_USER);
					lgEvent.data = user;
					lgEvent.dispatch(); //派发事件
					
					/***LoginEvent继承自com.adobe.cairngorm.control.CairngormEvent,* 用父类的方法dispatch派发事件;
					 * 其实CairngormEvent继承自flash.events.Event
					 * dispatch是CairngormEventDispatcher类封装IEventDispatcher
					 * 的dispatchEvent()方法
					 * **/
				} else {
					var vEvent:ValidationResultEvent;//定义校验出错事件
					//取出第一个出错事件
					vEvent = validatorResults[0] as ValidationResultEvent;
					//将光标定位到第一个出错的组件上
					(vEvent.target.source as UIComponent).setFocus();
				}
			}
		]]>
	</fx:Script>
	
	<fx:Declarations>
		<!--定义用户名和密码的输入校验类-->
		<mx:StringValidator id="unSV"
							source="{uName}"
							property="text"
							required="true"
							maxLength="10"
							tooLongError="用户名最长为10位"
							requiredFieldError="请填写用户名" />
		<mx:StringValidator id="pwSV"
							source="{pWord}"
							property="text"
							required="true"
							maxLength="10"
							tooLongError="密码最长为10位"
							requiredFieldError="请填写密码" />
	</fx:Declarations>
	
	<mx:Form  includeIn="initState">
		<mx:FormItem label="用户名" >
			<s:TextInput id="uName" />
		</mx:FormItem>
		<mx:FormItem label="密 码" >
			<s:TextInput id="pWord" displayAsPassword="true" />
		</mx:FormItem>
		<mx:FormItem>
			<s:Button id="submitBtn" click="submit(event)"  label="登陆" right="0" />
		</mx:FormItem>
	</mx:Form>
	<s:HGroup includeIn="loginState" top="20" left="10" >
		<s:Label  text="欢迎尊贵的用户:"/>
		<s:Label  id="cuName" text="{UserModelLocator.getInstance().currentUser.userName}" />
	</s:HGroup>
</s:Panel>
UserModelLocator.as文件源码如下:

package net.dreamhui.model
{
	import com.adobe.cairngorm.CairngormError;
	import com.adobe.cairngorm.CairngormMessageCodes;
	import com.adobe.cairngorm.model.ModelLocator;
	import flash.events.Event;
	import net.dreamhui.vo.UserVO;
	//绑定全局View数据
	[Bindable]
	public class UserModelLocator implements ModelLocator
	{
		private var _currentUser:UserVO;
		public static const LOGIN_YES:String = "loginYes";
		private static var instance:UserModelLocator;
		//单例模式
		public function UserModelLocator()
		{
			if(instance == !null)
			{
				throw new CairngormError(CairngormMessageCodes.SINGLETON_EXCEPTION,"UserModelLocator");
			}
			instance = this;
		}
		public static function getInstance():UserModelLocator
		{
			if(instance == null)
			{
				instance = new UserModelLocator();
			}
			return instance;
		}
		public function get currentUser():UserVO
		{
			return _currentUser;
		}
		/**
		 * 此赋值操作绑定loginYes事件,当输入数据合法时候,将改变当前的登录状态
		 * **/
		[Bindable("loginYes")]
		public function set currentUser(value:UserVO):void
		{
			_currentUser = value;
			dispatchEvent(new Event(UserModelLocator.LOGIN_YES));
		}
	}
}
LoginEvent.as源码如下:

package net.dreamhui.control
{
	import com.adobe.cairngorm.control.CairngormEvent;
	import net.dreamhui.vo.UserVO;
	public class LoginEvent extends CairngormEvent
	{
		//定义事件类型常量
		public static const LOGIN_USER:String = "loginUser";
		public function LoginEvent(type:String,bubbles:Boolean=false,cancelable:Boolean=false)
		{
			super(type,bubbles,cancelable);
		}
	}
}
LoginController.as源码如下:

package net.dreamhui.control
{
	import com.adobe.cairngorm.control.FrontController;
	import net.dreamhui.commands.LoginCommand;
	public class LoginController extends FrontController
	{
		public function LoginController()
		{
			initCommands();
		}
		/**注册Command*/
		private function initCommands():void
		{
			addCommand(LoginEvent.LOGIN_USER,LoginCommand);
		}
	}
}
LoginCommand.as源码如下:

package net.dreamhui.commands
{
	import com.adobe.cairngorm.commands.ICommand;
	import com.adobe.cairngorm.control.CairngormEvent;
	import mx.controls.Alert;
	import mx.rpc.IResponder;
	import net.dreamhui.business.LoginDelegate;
	import net.dreamhui.control.LoginEvent;
	import net.dreamhui.model.UserModelLocator;
	import net.dreamhui.vo.UserVO;
	public class LoginCommand implements ICommand,IResponder
	{
		public function LoginCommand()
		{
		}
		public function execute(event:CairngormEvent):void
		{
			var lgEvent:LoginEvent = LoginEvent(event);
			var user:UserVO = lgEvent.data;
			var delegate:LoginDelegate = new LoginDelegate(this);
			delegate.login(user); // 与后台的login方法名要相同
		}
		/**
		 * Command实现IResponder接口的两个方法result和fault;
		 * 我看了两份教程,前者是这样的:
		 * 1、Command实现com.adobe.cairngorm.business.Responder接口的onResult和onFault两个方法;
		 * 2、Command实现mx.rpc.IResponder接口的两个方法result和fault;
		 * 因为我在LoginDelegate没能实现将内部变量设置为com.adobe.cairngorm.business.Responder,
		 * 所以,我采用了第二种方案,通过。
		 * */
		// 收到返回值后由服务调用此方法
		public function result(event:Object):void
		{
			var cuUser:UserVO = event.result as UserVO;
			if(cuUser)
			{
				UserModelLocator.getInstance().currentUser = cuUser;
				//此赋值操作绑定loginYes事件,当输入数据合法时候,将改变当前的登录状态
			}else{
				Alert.show("用户名或密码错误,请重新填写");
			}
		}
		// 收到错误后由服务调用此方法
		public function fault(event:Object):void
		{
			trace("服务调用错误"+event.toString());
		}
	}
}
LoginDelegate.as源码如下:
package net.dreamhui.business
{
	import com.adobe.cairngorm.business.ServiceLocator;
	import mx.rpc.IResponder;
	import net.dreamhui.vo.UserVO;
	public class LoginDelegate
	{
		public var responder:IResponder;
		public var service:Object;
		public function LoginDelegate(responder:IResponder)
		{
			this.service = ServiceLocator.getInstance().getRemoteObject("loginService");
			//this.service = ServiceLocator.getInstance().getService("loginService");
			//我看的教程里采用下面的做法,程序运行没有问题,只是会有warning
			this.responder = responder;
		}
		public function login(user:UserVO):void
		{
			var call:Object = service.login(user); // 必须与远程的方法相对应
			//call.resultHandler = Delegate.create(responder,responder.onResult);
			//call.faultHandler = Delegate.create(responder,responder.onFault);
			//注释掉的部分是教程里的写法,可能是版本的问题,在我这儿是不对的
			call.addResponder(responder);
		}
	}
}
LoginServiceLocator.mxml文件源码如下:

<?xml version="1.0" encoding="utf-8"?>
<cairngorm:ServiceLocator
	xmlns:fx="http://ns.adobe.com/mxml/2009"
	xmlns:s="library://ns.adobe.com/flex/spark"
	xmlns:mx="library://ns.adobe.com/flex/mx"
	xmlns:cairngorm="http://www.adobe.com/2006/cairngorm">
	<fx:Declarations>
		<s:RemoteObject id="loginService" 
						destination="loginUser"
						showBusyCursor="true"
						/>
	</fx:Declarations>
</cairngorm:ServiceLocator>











(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读