Tapestry内部工作原理


【IT168 技术文档】

    tapestry的URL形如/examples/app?service=page/Admin 能够保证有效运行的一个非常重要的原因是,用有状态的javabean代替无状态的servlet构建一个tapestry应用。page是有状态的,他只能在一个线程里为一个用户处理一个request,而一个servelet,没有用户的状态,可以在并发线程中为任何数量同时发生的request提供服务。使用有状态的page遇到的问题和使用数据库的连接遇到的问题非常相似。 

    engine

    engine是每个tapestry应用的中心,它是一个负责支持和组织应用所有方面的对象,他把所有小的子系统绑在一起构成一个tapestry应用,它首先负责管理server端的状态,管理Visit对象及持久页面属性,他会被保存在session中。engine对象的service()方法,负责进来的request处理和把响应返回给客户端。 ApplicationServlet调用public boolean service(RequestContext context)方法figure 7.4,执行request处理,此服务不仅要进行很多的初始化工作,更重要的是它包括多级的异常捕捉、报告,任何未捕捉的异常会由异常页来呈现。过程如下:

    1).调用AbstractEnginer的protected void setupForRequest(RequestContext context)方法,确保engine对象被设置,这个方法很重要,细节可参看API文档,在覆写类方法的子类中,必须首先第一句调用这个方法 
    2).调用自己的getService(String name) 
    3).new RequestCycle(IEngine engine, RequestContext requestContext, IEngineService service, IMonitor monitor) 
    4).调用IEngineService的service(IEngineServiceView engine, IRequestCycle cycle, ResponseOutputStream output)方法 
    5).调用RequestCycle对象的cleanup() 
    6).调用自己的cleanupAfterRequest(IRequestCycle cycle)方法 

    Engine service

    Engine service是实现了IEngineService接口的对象,他包含很多创建和服务应用URL的方法,且全是在一个对象中,Engine service更象servlet,他能被很多线程共享,不能记录客户状态。tapeestry默认是有9个service,4个最长用的是home, page,direct和external,可见Table 7.3,大部分service有相对应的部件 
    IEngineService的service(IEngineServiceView engine, IRequestCycle cycle, ResponseOutputStream output)方法,IRequestCycle的一些方法调用等,各个service的调用是不相同,这些步之后各个service都要回调IEngine对象的renderResponse()方法,处理也是一样的。

 

home Service:

    1).调用IRequestCycle的getPage(String name),返回home page 
    2).调用IRequestCycle的activate(IPage page)方法,此方法为request设置最终返回客户端显示的活动页面,活动页面典型的由service设置,但因为可能被替换要显示的页面,也会经常被validator方法pageValidate(PageEvent event)改变,这个方法的操作过程如下:它调用page对象的validate(IRequestCycle cycle)方法,(validate()方法用于基本的安全验证,这个方法实际上并不执行任何检查Figure7.06,page对象可以有多个PageValidateListener,The validate()方法调用每个validator对象的pageValidate()。最通常的方法是page对象自己实现PageValidateListener接口,会自动注册成为自己的validator。validator可以通过throw a PageRedirectException激活不同的页面,当PageRedirectException异常被扔出,由service处理的request过程将被中止,被异常指定的页面被激活并被立马呈现给客户端。) 
    3).service对象回调engine的renderResponse()方法,将使活动页面被呈现并响应给客户端 

    page service: 
    除了service对象和home service不一样,其他步骤相同 

    direct service: 
    DirectLink和Form部件使用这个服务,这两个部件都实现IDirect接口,当处理form的submit时,会首先执行一个rewind动作,之后执行form指定的listener动作。direct service能够检查session是否过期,DirectLink和Form部件的“stateful”属性,默认为“false”,设置为“true”就可以进行session检查,当呈现响应时,direct service会生成URL,形如:/examples/app?service=direct/1/Guess/select,URL中的1,就标明这需要检查session是否过期, 

    一旦session过期,用户就会看到Session已经过期的页面,默认的是个很简陋的,可以创建一个命名为“StaleSession”的page,来给用户提供一个更友好的界面。处理请求,DirectService的service()方法处理过程:
    1).调用IRequestCycle的getPage(String name),返回page 
    2).调用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).调用IPage的getNestedComponent(String path),返回一个IDirect对象 
    4).调用IDirect对象的isStateful(),如果为true,session过期检查将要发生,检查HttpSession过期,StaleSessionException异常将被服务扔出 
    5).调用IRequestCycle的setServiceParameters(Object[] parameters),由service调用,service参数被解开并存入request cycle的serviceParameters属性中 
    6).调用IDirect对象的trigger(IRequestCycle cycle),调用部件的listener方法,执行相应的action 
    7).service对象回调engine的renderResponse()方法,将使活动页面被呈现并响应给客户端 

    需要注意的是,各方法调用顺序很重要,validate()发生的比较早,那时还不能访问service参数,session检查发生在validate()之后 

    对于DirectLink部件,trigger()方法内部处理过程: 
    1).调用IActionListenerr的actionTriggered(IComponent component,IRequestCycle cycle)方法 
1.1).通过反射机制调用listener方法 
    对于Form部件,trigger()方法执行,要执行rewind,内部过程Figure 7.12: 
    1).调用IRequestCycle的rewindForm(IForm form,String targetActionId)方法 
    1.1).调用page对象的beginPageRender(),触发适当的事件 
    1.2).回调IForm对象的rewind(IMarkupWriter writer,IRequestCycle cycle) 
    1.2.1).调用IForm对象的render(IMarkupWriter writer, IRequestCycle cycle) 
    1.2.2).调用监听方法等 
    1.3).调用page对象的endPageRender(),触发适当的事件 


上一篇 下一篇

分享

热门文章