到新公司已经一个礼拜了,今天刚好是第七个工作日,十一之前已经写好的demo,今天来总结一下。
初次接触flex,公司采用pureMVC和BlazeDS框架,在一个即将开始做的项目里面,我参照PM写的登录功能,在这个工程里面做了一个很简单的功能,填写一个表单,向数据库里面增加一条数据,然后列出这张表里面的所有数据。在做这个小功能时,慢慢地体会到了flex的强大与pureMVC的思想,完全使界面与操作,模型处理以及控制分开。
首先介绍一个这个工程的架构:
分为flex工程和java工程。在两个IDE里面coding,从flex端直接运行,java端服务开启,以debug模式启动tomcat.
java端采用spring,ibatis框架
flex采用pureMVC,BlazeDS框架
我先不介绍pureMVC的东西了,这个我现在还在体会中,以后有时间了写下详细介绍,今天算是做一个简单的总结。因为才接触,有些地方可能不准确,能提出改进建议就更期待了。
首先,在ApplicationFacade的initializeController方法中注册Controller的类,我这里叫作feeCommand。最开始取名时没想到,flex是完全面象对象的,这个feeCommand也是一个类,最好是大写开头。
注册这个feeCommand代码:
registerCommand(GlobalCommandNots.FEE_DEMO_COMMAND,feeCommand);
//feeCommand是一个类名
GlobalCommandNots是一个类,专门存放全局变量。这里面是定义控制参数。
public static const FEE_DEMO_COMMAND:String ="Facade.fee_demo";
程序run的时候,最先到ApplicationFacade里面找到注册的command,然后在command里面会有proxy代理,proxy负责与后端通信。
public class feeCommand extends SimpleCommand implements ICommand
{
//得到FeeProxy对象。
public function get feeProxy():FeeProxy
{
var proxy:FeeProxy;
if(this.facade.hasProxy(FeeProxy.PROXY_NAME)){
proxy = this.facade.removeProxy(FeeProxy.PROXY_NAME) as FeeProxy;
}else{
proxy=new FeeProxy();
this.facade.registerProxy(proxy);
}
return proxy;
}
override public function execute(notification:INotification):void
{
switch(notification.getType()){
case GlobalNotifications.TO_ADD_FEE:
var fe:fee=notification.getBody() as fee;
if(fe==null) break ;
var param:Object=new Object();
param.moduleId=StringUtil.trim(fe.moduleId.text);
param.moduleType=StringUtil.trim(fe.moduleType.text);
param.moduleName=StringUtil.trim(fe.moduleName.text);
param.parentId=StringUtil.trim(fe.parentId.text);
feeProxy.addOne(param);//这里调用proxy里面的方法,而在proxy里面,又与后台java端通信,调用java里面的方法。
break;
default:
break;
}
}
}
FeeProxy.as代码:
public class FeeProxy extends Proxy
{
public static const PROXY_NAME:String="com.tongcard.tcc.main.model.proxy.FeeProxy";
private var tccRemote:TccRemoteObject;
public function FeeProxy(proxyName:String=null, data:Object=null)
{
super(PROXY_NAME, data);
tccRemote = new TccRemoteObject();
tccRemote.destination = 'feeServiceRemoting'; //这里对应spring的<bean id="feeServiceRemoting" class="org.springframework.flex.remoting.RemotingDestinationExporter">
}
public function addOne(param:Object):void
{
tccRemote.addOne(param);//调用后台的FeeService里面的addOne方法。
tccRemote.addEventListener(ResultEvent.RESULT,addOneResultHandler);
}
private function addOneResultHandler(e:ResultEvent):void
{
if(e.result.status=="success"){
this.sendNotification(GlobalNotifications.QUERY_FEE_LIST,e.result.feeList as ArrayCollection,null);
}else{
Alert.show("fail to add one ");
}
// tccRemote.getFeeList();//调用后台的的的FeeService里面的getFeeList方法。
// tccRemote.addEventListener(ResultEvent.RESULT,feeListResultHandler);
}
feeproxy主要负责与java后端通信,如果添加成功就发通知,通知会发给专门负责处理界面的类FeeMediator
if(e.result.status=="success"){
this.sendNotification(GlobalNotifications.QUERY_FEE_LIST,e.result.feeList as ArrayCollection,null);
注意,这里是指添加一条数据成功后,返回了一个状态,当状态为成功时,发送一个通知,这里是将返回的feeList在发通知时一起发出去的。然后FeeMediator处理通知
case GlobalNotifications.QUERY_FEE_LIST:
var array: ArrayCollection =notification.getBody() as ArrayCollection;
fe.removeAllChildren();
var flist:FeeList =new FeeList();
fe.addChild(flist);
flist.feeDataGrid.dataProvider=array;
这里的var array: ArrayCollection =notification.getBody() as ArrayCollection;就是feeProxy里面的
this.sendNotification(GlobalNotifications.QUERY_FEE_LIST,e.result.feeList as ArrayCollection,null);//这里是将返回的feeList在发通知时一起发出去的。
并且,这里面的flist.feeDataGrid.dataProvider=array;是将得到的ArrayList集合赋值给FeeList.mxml里面的DataGrid组件,我这里没有用绑定。
FeeList.mxml代码:
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
<mx:HBox id="sss"/>
<mx:DataGrid x="20" y="52" height="168" width="357" id="feeDataGrid">
<mx:columns>
<mx:DataGridColumn headerText="编号ID" dataField="moudleId"/>
<mx:DataGridColumn headerText="费用名称" dataField="moduleName"/>
<mx:DataGridColumn headerText="费用类别" dataField="feeType"/>
<mx:DataGridColumn headerText="父级ID" dataField="moduleParentId"/>
</mx:columns>
</mx:DataGrid>
</mx:Canvas>
FeeMediator.as的代码:
public class FeeMediator extends Mediator
{
public static const MEDAITOR_NAME:String = "com.tongcard.tcc.main.view.firstdemo.FeeMediator";
public function FeeMediator(mediatorName:String=null, viewComponent:Object=null)
{
super(mediatorName, viewComponent);
fe.submitBut.addEventListener(MouseEvent.CLICK,insert);
//fe.viewList.addEventListener(MouseEvent.CLICK,onClickToFeeList);
}
public function get fe():fee
{
return this.getViewComponent() as fee;
}
private function insert(e:MouseEvent):void
{
//Alert.show("add add");
this.sendNotification(GlobalCommandNots.FEE_DEMO_COMMAND,
fe,GlobalNotifications.TO_ADD_FEE);
}
override public function listNotificationInterests():Array
{
return [GlobalNotifications.TO_ADD_FEE,GlobalNotifications.QUERY_FEE_LIST];
}
override public function handleNotification(notification:INotification):void
{
switch(notification.getName()){
case GlobalNotifications.TO_ADD_FEE:
this.sendNotification(GlobalCommandNots.FEE_DEMO_COMMAND,new Object(),"addFee");
break;
case GlobalNotifications.QUERY_FEE_LIST:
var array: ArrayCollection =notification.getBody() as ArrayCollection;
fe.removeAllChildren();
var flist:FeeList =new FeeList();
fe.addChild(flist);
flist.feeDataGrid.dataProvider=array;
break;
default:
break;
}
}
}
FeeMediator构造方法里面就注册了监听,
fe.submitBut.addEventListener(MouseEvent.CLICK,insert);
表示点击fee.mxml页面上的提交按钮时调用insert方法。而insert方法里面将添加的通知发给FeeCommand,在FeeCommand里面的
override public function execute(notification:INotification):void
{
switch(notification.getType()){
case GlobalNotifications.TO_ADD_FEE:
var fe:fee=notification.getBody() as fee;
if(fe==null) break ;
var param:Object=new Object();
param.moduleId=StringUtil.trim(fe.moduleId.text);
param.moduleType=StringUtil.trim(fe.moduleType.text);
param.moduleName=StringUtil.trim(fe.moduleName.text);
param.parentId=StringUtil.trim(fe.parentId.text);
feeProxy.addOne(param);//这里调用proxy里面的方法,而在proxy里面,又与后台java端通信,调用java里面的方法。
break;
default:
break;
}
这里是将表单中的信息封装到一个Object的param里面,然后调用feeProxy里面的addOne.
而feeProxy里面的addOne又是什么样的?
public function addOne(param:Object):void
{
tccRemote.addOne(param);//调用后台的FeeService里面的addOne方法。
tccRemote.addEventListener(ResultEvent.RESULT,addOneResultHandler);
}
feeProxy负责与后端通信。tccRemote.addOne(param);//调用后台的FeeService里面的addOne方法。
那再看看后端这个方法:
public Map addOne(Map<String,Object> map){
resultMap.clear();
String moduleId=(String)map.get("moduleId");
String moduleName=(String)map.get("moduleName");
String moduleType=(String)map.get("moduleType");
String parid=(String)map.get("parentId"); //从这里取出前端flex传来的param里面的parentId的参数。
FeeMoudel feem=new FeeMoudel();
feem.setMoudleId(moduleId);
feem.setFeeType(moduleType);
feem.setModuleName(moduleName);
feem.setModuleParentId(parid);
try {
if(feeManager!=null){
feeManager.addOne(feem);
List feeList=getFeeList();
resultMap.put("feeList", feeList);
resultMap.put("status", "success");
}else{
resultMap.put("status", "fail");
System.out.println("feemanager is null");
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return resultMap;
}
这里的
String moduleId=(String)map.get("moduleId");
String moduleName=(String)map.get("moduleName");
String moduleType=(String)map.get("moduleType");
String parid=(String)map.get("parentId"); //从这里取出前端flex传来的param里面的parentId的参数。
与flex端的
var param:Object=new Object();
param.moduleId=StringUtil.trim(fe.moduleId.text);
param.moduleType=StringUtil.trim(fe.moduleType.text);
param.moduleName=StringUtil.trim(fe.moduleName.text);
param.parentId=StringUtil.trim(fe.parentId.text);
feeProxy.addOne(param);//这里调用proxy里面的方法,而在proxy里面,又与后台java端通信,调用java里面的方法。
是根据key关联起来的。
这里的模型数据类是FeeMoudel,它有以下几个属性:
private String moudleId;
private String moduleName;
private String feeType;
private String moduleParentId;
spring的配置:
<bean id="feeManager" class="com.tongcard.tcc.feedemo.manager.impl.FeeManagerImpl"></bean> <bean id="feeService" class="com.tongcard.tcc.feedemo.FeeService"></bean> <bean id="feeServiceRemoting" class="org.springframework.flex.remoting.RemotingDestinationExporter"> <property name="messageBroker" ref="_messageBroker"></property> <property name="service" ref="feeService"></property> </bean>
其中,<bean id="feeServiceRemoting" class="org.springframework.flex.remoting.RemotingDestinationExporter">就是与flex通信的RemoteObject关联的配置。
Ibatis的配置
<sqlMap namespace="feesql"> <typeAlias alias="fee" type="com.tongcard.tcc.feedemo.moudel.FeeMoudel" /> <resultMap class="fee" id="feeListMap"> <result property="moudleId" column="module_id"/> <result property="moduleName" column="module_name"/> <result property="feeType" column="fee_type"/> <result property="moduleParentId" column="parent_module_id"/> </resultMap> <select id="getFeeList" resultMap="feeListMap"> select * from fee_module </select> <insert id="addOnefee" parameterClass="fee"> insert into fee_module (module_id,module_name,fee_type,parent_module_id) values (#moudleId#,#moduleName#,#feeType#,#moduleParentId#) </insert> </sqlMap>