您的位置:首页 > 编程语言 > Java开发

Cairngorm+BlazeDS整合Flex+Java的Demo(实例)

2011-07-07 16:37 393 查看
今天学习Cairngorm,找了份教程,写了个Demo,以记录并分享学习过程。 Cairngorm的各个部分: ModelLocator:在一个地方存储程序中所有的值对象(ValueObjects,数据)并共享变量。它与HTTP Session对象相类似,不过它存储在Flex客户端,而不是存储在一个中间层程序服务器的服务器端。
View(视图):一个或多个Flex组件(Button,panel,combo Box,Tile等等)绑定到一起形成的一个特定的个体,使用ModelLocator中的数据并且针对用户的交互动作(如点击,鼠标滑过,拖拽等)产生自定义的CairngormEvents。
FrontController(前端控制器):接受CairngormEvents并且将它们映射到CairngormCommands。
Command(命令):处理业务逻辑,调用CairngormDelegates或其他的Commands,以及更新ModelLocator中存储的值对象和变量。
Delegate(委托):由一个Command创建,它将远程过程实例化并且将结果返回给Command。
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:完成用户登录在后台进行验证合法性,并反馈给前台。
工具及环境介绍:详见我的上篇文章,BlazeDS实现Flex和Java通信的Demo
版本说明:
Flex:Flex 4;
ActionScript:ActionScript 3;
Java JDK:jdk1.6.0_20
Cairngorm,我用的是版本2.2,好像Cairngorm 3已经发布了,但是官网没提供下载。下载cairngorm2_2_1-bin.zip,我们要用的已经打包好的资源文件Cairngorm.swc,将其拷贝到Flex工程的libs目录下面即可。
后台Java服务端项目CairngormDemo工程组成:



相应代码:
UserVO.java

package net.dreamhui.java;
public class UserVO {
public String userName;
public String passWord;
//和ActionScript对应得构造方法
public UserVO()
{
}
//getters & setters
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;
}
}


LoginUser.java
package net.dreamhui.java;
public class LoginUser {
public UserVO currentUser;
private String uName;
private String pWord;
//Flex端要调用的服务
public UserVO login(UserVO par_user)
{
//UserVO par_user2 = UserVO(par_user);
uName = par_user.userName;
pWord = par_user.passWord;
if(uName.equalsIgnoreCase("wwh")&&pWord.equalsIgnoreCase("wwh"))
{
return par_user;
//return "欢迎用户:"+uName;
}
else{
return null;
//return "用户名或密码错误,请重新输入";
}
}
}

配置文件(要添加的内容):
remoting-config.xml
<destination id="loginUser">
<properties>
<source>net.dreamhui.java.LoginUser</source>
</properties>
</destination>

前台Flex工程CairngormDemo工程组成:



按照 ValueObjects模型(UserVO.as)——>模型定位(UserModelLocator.as)——>视图(loginView.mxml及主应用视图CairngormDemo.mxml)——>事件(LoginEvent.as)——>前端控制器(LoginController.as)——>Command(LoginCommand.as)——>委派代理(LoginDelegate.as)——>服务定位(LoginServiceLocator.mxml)依次的相应代码如下(因为文件中注释较多,不多写注解):
UserVO.as
package net.dreamhui.vo
{
/**
* 我看的教程里面讲绑定ValueObject到远程Java类的方法是这样的,
* public static var registered:Boolean = this.registerClass();
* 可能又是版本问题,在我这儿是通不过的,我到网上找到了如下的解决方法:
* [RemoteClass(alias="net.dreamhui.java.UserVO")],
* 估计是我看的教程版本太低了,呵呵
* */
import com.adobe.cairngorm.vo.ValueObject;
[Bindable]
[RemoteClass(alias="net.dreamhui.java.UserVO")]
public class UserVO implements ValueObject
{
private var _userName:String;
private var _passWord:String;
/**
* 为了实现远程Class之间的绑定,构造方法必须形式上完全一致,
* 包括参数的个数和类型,否则会出现异常。
* */
public function UserVO()
{
}
//getters & setters
public function get userName():String
{
return _userName;
}
public function set userName(value:String):void
{
_userName = value;
}
public function get passWord():String
{
return _passWord;
}
public function set passWord(value:String):void
{
_passWord = value;
}
}
}
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));
}
}
}


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)">
<!--~~~~~~~~~~~~~~~~~~~~~~Script~~~~~~~~~~~~~~~~~~~~~~-->
<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>
<!--~~~~~~~~~~~~~~~~~~~~~~states~~~~~~~~~~~~~~~~~~~~~~-->
<s:states>
<s:State name="initState"/>
<s:State name="loginState"/>
</s:states>
<!--~~~~~~~~~~~~~~~~~~~~~~Declarations~~~~~~~~~~~~~~~~~~~~~~-->
<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>
<!--~~~~~~~~~~~~~~~~~~~~~~UI Components~~~~~~~~~~~~~~~~~~~~~~-->
<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>


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


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
{
//Alert.show("execute");
var lgEvent:LoginEvent = LoginEvent(event);
var user:UserVO = lgEvent.data;
var delegate:LoginDelegate = new LoginDelegate(this);
delegate.login(user);
}
/**
* 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事件,当输入数据合法时候,将改变当前的登录状态
//Alert.show(cuUser.userName);
}
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">
<!--~~~~~~~~~~~~~~~~~~~~~~Declarations~~~~~~~~~~~~~~~~~~~~~~-->
<fx:Declarations>
<s:RemoteObject id="loginService"
destination="loginUser"
showBusyCursor="true"
/>
</fx:Declarations>
</cairngorm:ServiceLocator>

最后工程运行结果:

OK,完成。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: