external Service
1).调用IRequestCycle的getPage(String name),返回page
2).调用IRequestCycle的setServiceParameters(Object[] parameters),由service调用
3).调用IRequestCycle的activate(IPage page)方法,此方法为request设置最终返回客户端显示的活动页面,活动页面典型的由service设置,但因为可能被替换要显示的页面,也会经常被validator方法pageValidate(PageEvent event)改变,这个方法的操作过程如下:它调用page对象的validate(IRequestCycle cycle)方法,(validate()方法用于基本的安全验证,这个方法实际上并不执行任何检查,page对象可以有多个PageValidateListener,The validate()方法调用每个validator对象的pageValidate()。最通常的方法是page对象自己实现PageValidateListener接口,会自动注册成为自己的validator。validator可以通过throw a PageRedirectException激活不同的页面,当PageRedirectException异常被扔出,由service处理的request过程将被中止,被异常指定的页面被激活并被立马呈现给客户端。)
3).调用IExternalPage的activateExternalPage(Object[] parameters, IRequestCycle cycle)
4).service对象回调engine的renderResponse()方法,将使活动页面被呈现并响应给客户端
从池中获得一个页面
虽然采用池化技术,因为page众多,我认为,在最开始池中是没有page的,只有第一次访问生成一个完整page,直接返回给request使用,使用完毕page返回池中等待复用。
Figure 7.19 IRequestCycle的getPage(String name)方法返回一个page实例,这个实例被request cycle对象在整个request期间缓存,将来调用同名page名字的getPage()会返回相同实例,getPage()方法内部步骤是,
1).用IPageSource的getPage(IRequestCycle cycle, String pageName, IMonitor monitor)方法,IPageSource就是page池,他能实例化一个新的page实例,如果池中没有可用的page实例,page实例调用自己的attach(IEngine value)以把自己绑定到一个具体的engineh上,一直到request cycle结束,才解除绑定返回池中。
2).调用page的setRequestCycle(IRequestCycle cycle)
3).调用IEngine的getPageRecorder(String pageName,IRequestCycle cycle),IPageRecorder是一个对象,负责追踪page的持久页面属性变化的,当持久页面属性改变了,新值就会被记录在HttpSession中。page持久状态是特定于一个专门用户,完全和page实例分开的。IPageRecorder通过简单的通知机制被钩入page实例,IPageRecorder观察到持久属性改变,就会他作为一个命名的session属性把持久属性值安全的保存到HttpSession,各自的持久页面属性被作为独自的HttpSession属性保存
4).调用IPageRecorder的rollback(IPage page),将页面持久属性恢复到HttpSession属性保存的值
创建一个新Page实例
当请求page,而池中又没有实例可用,page source会利用PageLoader(是类不是IPageLoader接口)来创建一个page实例figure 7.20:
PageLoader不是threadsafe,PageSource要创建一个新的PageLoader实例为每一个要装载的页面,为解决多线程的问题
PageLoader的IPage loadPage(String name,
INamespace namespace,
IRequestCycle cycle,
IComponentSpecification specification)
过程:
1).new一个page实例,java page class被实例化
2).初始化属性,page的初始属性被设置,包括page名字
3).page实例调用自己的attach(IEngine value)以把自己绑定到一个具体的engineh上
4).page包含的部件被递归创建,每一个部件被创建,page loader就会调用部件的finishLoad()方法,从BaseComponent类继承的部件在这时也会装载他的模板
5).page的finishLoad()方法被调用
一旦page的finishLoad()方法执行完毕,一个初始化和配置过的完整的page对象被返回给request cycle。对于页面和部件来说,当在page or component specification中对有的初始化不能被表达时,重载后的finishLoad()方法是个进行这种最终初始化的好地方,经常这类初始化要涉及page中的其他部件。finishLoad()有两个方法,
public void finishLoad(
IRequestCycle cycle,
IPageLoader loader,
IComponentSpecification specification);
protected void finishLoad();
尽量重载protected的无参的finishLoad(),且无需先调用父类的方法,除非要使用到3个参数,才会重载public的,且当重载public的带3个参数的方法时,必须先调用父类的public的同名方法,一旦调用失败,就会造成加载page或component的模板失败,也会造成其他方面的影响