igenko学习_登陆部分客户端逻辑
大约在08年年初的时候就知道igenko这个项目的存在,那个时候,还是刚刚起步,不过更新速度很快。
之所以关注这个项目是因为技术架构和springside有很大的互补的地方,两者都使用了spring,但是springside很着重展示后台部分(当然了,这个随着小胖的加入,前台的grid会更强),而igenko则是更加着重前台展现(它使用了flex作为客户端)。另外,igenko值得关注的原因还有,他使用了jbpm作为工作流,并且项目的目标很明确,一个基于ria展现的cms系统。
本篇关注一下igenko的客户端登陆逻辑。
对于登陆的后台部分逻辑是使用的spring-acegi,所以后台的部分和springside非常的相似,如果谁觉得需要更多了解,直接去看springside的wiki是最省事的了。而前台的逻辑中,igenko试用了puremvc作为其mvc的框架,更有意思的是,bouiaw找了一个prana的开源框架充来当spring的角色,完成ioc的注入。
在puremvc的逻辑中,需要在view(也就是mxml中)触发出事件,而Mediator(view的一部分,相当于view的逻辑部分)来监听这个事件。继而Mediator将会发出Notify。系统中其他地方接收这个通知,继而进行相关的逻辑处理,也就是说,view层的Mediator发送了消息给controll,继而view层退出这个事件了处理。
上边的逻辑大家可以在,org.igenko.client.backoffice.view.common.BackofficeLogin这个类中看到,这个类触发了一下的事件:
dispatchEvent( new Event( BackofficeLogin.LOGIN ) );
而org.igenko.client.backoffice.view.common.mediator.BackofficeLoginMediator则监听这个事件,如下:
backofficeLogin.addEventListener( BackofficeLogin.LOGIN, login );
继而在login方法中,处理逻辑:
1
private
function login( event:Event ) :
void
2 {
3 sendNotification(NotificationConstants.LOGIN, new User(backofficeLogin.username.text, backofficeLogin.password.text));
4 }
这个当中就发送了我说的那个通知。接下来就是controll层来处理这个通知。
2 {
3 sendNotification(NotificationConstants.LOGIN, new User(backofficeLogin.username.text, backofficeLogin.password.text));
4 }
而controll层就是puremvc中的commond,按着文档中的逻辑,那个通知触发那个commond是由facade这个接口来负责的。
这个时候就是igenko的一个有意思的地方了。在puremvc的文档中,应该在facade当中将commond注册进去,但是ingeko只是
override
protected
function initializeController():
void
{
super .initializeController();
registerCommand(NotificationConstants.SERVICE_ERROR, ShowServiceError);
registerCommandByConfigName(NotificationConstants.STARTUP, NotificationConstants.STARTUP_CMD);
}
当中看似没有注册任何关于Login的commond,但是当关注到
NotificationConstants.STARTUP_CMD这个commond的时候,就会发现如下的代码:{
super .initializeController();
registerCommand(NotificationConstants.SERVICE_ERROR, ShowServiceError);
registerCommandByConfigName(NotificationConstants.STARTUP, NotificationConstants.STARTUP_CMD);
}
public
function set commands(_commands:Array):
void
{
logger.debug( " entering set commands " );
for each ( var c : Object in _commands ) {
var commandInstance:IIocCommand = c as IIocCommand;
logger.debug( " addSubCommand " + commandInstance);
addSubCommand(commandInstance);
}
}
这说明,facade加入了一个StartupCommand,而StartupCommand又继承了IocManagedMacroCommand这个可以执行多个commond的类,那么就是相当于facade注册很多个commond.
logger.debug( " entering set commands " );
for each ( var c : Object in _commands ) {
var commandInstance:IIocCommand = c as IIocCommand;
logger.debug( " addSubCommand " + commandInstance);
addSubCommand(commandInstance);
}
}
接下来的问题就是,StartupCommand中的 _commands这个数组是那里来的呢?
答案就是,ioc注入的。
在ApplicationContextCommon.xml中可以发现如下的配置:
<
object id
=
"
startupCommand
"
class
=
"
org.igenko.client.common.controller.StartupCommand
"
>
< property name = " commands " >
< array >
< ref > registerCommandsCommand </ ref >
< ref > registerProxiesCommand </ ref >
< ref > registerMediatorsCommand </ ref >
</ array >
</ property >
</ object >
对于当中的
registerCommandsCommand
是如下的:< property name = " commands " >
< array >
< ref > registerCommandsCommand </ ref >
< ref > registerProxiesCommand </ ref >
< ref > registerMediatorsCommand </ ref >
</ array >
</ property >
</ object >
<
object id
=
"
registerCommandsCommand
"
class
=
"
org.igenko.client.common.controller.startup.RegisterCommandsCommand
"
>
< property name = " commands " >
< array >
<!-- Login commands -->
< object class = " org.igenko.client.common.controller.DynamicObject " >
< property name = " notification " >
< object class = " org.pranaframework.ioc.factory.config.FieldRetrievingFactoryObject " >
< property name = " staticField " value = " org.igenko.client.common.NotificationConstants.LOGIN " />
</ object >
</ property >
< property name = " command " ref = " loginCommand " />
</ object >
< object class = " org.igenko.client.common.controller.DynamicObject " >
< property name = " notification " >
< object class = " org.pranaframework.ioc.factory.config.FieldRetrievingFactoryObject " >
< property name = " staticField " value = " org.igenko.client.common.NotificationConstants.LOGOUT " />
</ object >
</ property >
< property name = " command " ref = " logoutCommand " />
</ object >
<!-- Webcompiler commands -->
< object class = " org.igenko.client.common.controller.DynamicObject " >
< property name = " notification " >
< object class = " org.pranaframework.ioc.factory.config.FieldRetrievingFactoryObject " >
< property name = " staticField " value = " org.igenko.client.common.NotificationConstants.COMPILE_WIDGET " />
</ object >
</ property >
< property name = " command " ref = " compileWidgetCommand " />
</ object >
</ array >
</ property >
</ object >
< property name = " commands " >
< array >
<!-- Login commands -->
< object class = " org.igenko.client.common.controller.DynamicObject " >
< property name = " notification " >
< object class = " org.pranaframework.ioc.factory.config.FieldRetrievingFactoryObject " >
< property name = " staticField " value = " org.igenko.client.common.NotificationConstants.LOGIN " />
</ object >
</ property >
< property name = " command " ref = " loginCommand " />
</ object >
< object class = " org.igenko.client.common.controller.DynamicObject " >
< property name = " notification " >
< object class = " org.pranaframework.ioc.factory.config.FieldRetrievingFactoryObject " >
< property name = " staticField " value = " org.igenko.client.common.NotificationConstants.LOGOUT " />
</ object >
</ property >
< property name = " command " ref = " logoutCommand " />
</ object >
<!-- Webcompiler commands -->
< object class = " org.igenko.client.common.controller.DynamicObject " >
< property name = " notification " >
< object class = " org.pranaframework.ioc.factory.config.FieldRetrievingFactoryObject " >
< property name = " staticField " value = " org.igenko.client.common.NotificationConstants.COMPILE_WIDGET " />
</ object >
</ property >
< property name = " command " ref = " compileWidgetCommand " />
</ object >
</ array >
</ property >
</ object >
可以看见第一个注入的就是 loginCommand .
继而,我们可以看见经过一系列的寻找,触发了view层的login事件,最后会到达到 org.igenko.client.common.controller.login.LoginCommand类的excute方法(很类似struts1吧,连方法名都一致)。如下:
override
public
function execute(notification:INotification):
void
{
userToLogin = notification.getBody() as User ;
// inserted via IoC
ILoginDelegate(delegate).checkLogin(userToLogin.name, userToLogin.password);
}
{
userToLogin = notification.getBody() as User ;
// inserted via IoC
ILoginDelegate(delegate).checkLogin(userToLogin.name, userToLogin.password);
}
接下来就是通过remote object与后端通信了。
希望这个摘记对于刚刚接触的人有帮助。对于文中的不合理之处,欢迎指出!