首先列出几个部件(相关代码见原文)
MainTemplate.jsp 有两个自定义标签,一个定义容器的container,另一个定义容器中的元素include
此文件为显示页面设置了一个框架(模板),通过自定义标签,可以动态加入内容。
View.xml <views>
<view>
</view>
</views>
对于每个页面,都有view元素,此中指定所用的模板,还可以包括一个或多个的container元素。这些container标签中,指定了include标签需要填入的内容。
public interface View 接口函数:getURL hasContainer getTemplate
ForntController.java 1.制定或创建Dispatcher
2.dispatcher.getNextPage(request,context)
3.forward
CompositerDispatcher.java 1.当setContext时,首先解析View.xml文件,然后把其中不同的<view></view>对间的东西作为View对象(实现View接口的类对象)保存起来。这时候,用到HashMap,把view对象,通过名字索引起来。
2.getNextPage时,从request中得到view的索引,然后从HashMap中取出view(不存在,则指向默认页),然后将它存储在request中。最后返回的页面是view的getTemplate结果
ContainerTag.java 先从存于pageContext的request中取得view,然后逐个执行这个tag内的东西
ContainerIncludeTag.java 查找父标签 ContainerTag,从中得到view,并得到给定容器和标签的URL,并让pageContext包含它。
下面考虑一个具体的流程,姑且叫他串串烧吧。
串串烧
假设在一个Html文件中按了提交按钮,则产生一个request,比如说,请求Page1,则FrontController接受该request。从request中,我们知道需要哪个dispatch来处理这个请求。现在假定request含有的信息指定了CompositeDispatcher。FrontController先找该CompositeDispatcher是否先前创建过并保存于session中了。当然,第一次是找不到的,就只能自己创建一个CompositeDispatcher了(使用Class.forName)。
第一次创建CompositeDispatcher后,FrontController就调用CompositeDispatcher的setContext方法。该方法读入View.xml文件,并用DOM解析之。View.xml中每一个<view></view>tag对之间的信息均被保存在一个View类中,保存的信息有container的信息,label的信息,对应的URL,最后还有template。然后,用到HashMap,把view对象,通过名字索引起来。对应于这个例子,我们在HashMap中索引了两个view,key分别是Page1,Page2。现在看看为什么getURL方法有两个参数呢,这是因为一个view对象中,可以有多个container。
调用完setContext后,控制权转到FrontController,他把刚生成的CompositeDispatcher保存到session中,以备后用。
以上是创建CompositeDispatcher的过程,之后由FrontController调用CompositeDispatcher的getNextPage方法。我们来看getNextPage做了些什么,他从request中得到view的索引,然后从HashMap中取出view(不存在,则指向默认页),然后将它存储在request中。这边,我们request中包含的请求是Page1,所以我们找到它所对应的view,这个view回来具体化模板。最后返回的页面就是view的template页面,即MainTemplate.jsp.
好了,控制权又转到了FrontController,他通过forward调用,又把控制权交给了MainTemplate.jsp,因为这个页面就是调度器得到的下一个页面。
下面就是MainTemplate.jsp的处理过程了。它首先碰到了自定义标签container,name=“main”,于是我们找到ContainerTag类,调用setName方法,把“main”保存于类的实例中。此时,startTag结束了,需要调用doStartTag,他把存储于request的view取出来,当然要先看看这个view是否在container标签指定的容器中(setName的name),若不是,就没有理由用这个view来具体化该标签内的东西了。接着就是顺序执行标签中的内容。它又碰到了一个自定义标签,include,找ContainerIncludTag,先调用setLable,然后doEndTag。doEndTag时,首先查找父标签,ContainerTag,然后从中得到view,我们再从view中得到具体化的内容,这边就是url,最后让这个页面包含这个url,pageContext.include,在之后的现实,就会显示出该url指向的内容。这样,当三条include自定义标签都处理完后,我们就在一个页面中,嵌入了三个子页面。
若当我们再要request Page2时,同样处理,只是有些已经初始化的东西,就不必再初始化了。
MainTemplate.jsp 有两个自定义标签,一个定义容器的container,另一个定义容器中的元素include
此文件为显示页面设置了一个框架(模板),通过自定义标签,可以动态加入内容。
View.xml <views>
<view>
</view>
</views>
对于每个页面,都有view元素,此中指定所用的模板,还可以包括一个或多个的container元素。这些container标签中,指定了include标签需要填入的内容。
public interface View 接口函数:getURL hasContainer getTemplate
ForntController.java 1.制定或创建Dispatcher
2.dispatcher.getNextPage(request,context)
3.forward
CompositerDispatcher.java 1.当setContext时,首先解析View.xml文件,然后把其中不同的<view></view>对间的东西作为View对象(实现View接口的类对象)保存起来。这时候,用到HashMap,把view对象,通过名字索引起来。
2.getNextPage时,从request中得到view的索引,然后从HashMap中取出view(不存在,则指向默认页),然后将它存储在request中。最后返回的页面是view的getTemplate结果
ContainerTag.java 先从存于pageContext的request中取得view,然后逐个执行这个tag内的东西
ContainerIncludeTag.java 查找父标签 ContainerTag,从中得到view,并得到给定容器和标签的URL,并让pageContext包含它。
下面考虑一个具体的流程,姑且叫他串串烧吧。
串串烧
假设在一个Html文件中按了提交按钮,则产生一个request,比如说,请求Page1,则FrontController接受该request。从request中,我们知道需要哪个dispatch来处理这个请求。现在假定request含有的信息指定了CompositeDispatcher。FrontController先找该CompositeDispatcher是否先前创建过并保存于session中了。当然,第一次是找不到的,就只能自己创建一个CompositeDispatcher了(使用Class.forName)。
第一次创建CompositeDispatcher后,FrontController就调用CompositeDispatcher的setContext方法。该方法读入View.xml文件,并用DOM解析之。View.xml中每一个<view></view>tag对之间的信息均被保存在一个View类中,保存的信息有container的信息,label的信息,对应的URL,最后还有template。然后,用到HashMap,把view对象,通过名字索引起来。对应于这个例子,我们在HashMap中索引了两个view,key分别是Page1,Page2。现在看看为什么getURL方法有两个参数呢,这是因为一个view对象中,可以有多个container。
调用完setContext后,控制权转到FrontController,他把刚生成的CompositeDispatcher保存到session中,以备后用。
以上是创建CompositeDispatcher的过程,之后由FrontController调用CompositeDispatcher的getNextPage方法。我们来看getNextPage做了些什么,他从request中得到view的索引,然后从HashMap中取出view(不存在,则指向默认页),然后将它存储在request中。这边,我们request中包含的请求是Page1,所以我们找到它所对应的view,这个view回来具体化模板。最后返回的页面就是view的template页面,即MainTemplate.jsp.
好了,控制权又转到了FrontController,他通过forward调用,又把控制权交给了MainTemplate.jsp,因为这个页面就是调度器得到的下一个页面。
下面就是MainTemplate.jsp的处理过程了。它首先碰到了自定义标签container,name=“main”,于是我们找到ContainerTag类,调用setName方法,把“main”保存于类的实例中。此时,startTag结束了,需要调用doStartTag,他把存储于request的view取出来,当然要先看看这个view是否在container标签指定的容器中(setName的name),若不是,就没有理由用这个view来具体化该标签内的东西了。接着就是顺序执行标签中的内容。它又碰到了一个自定义标签,include,找ContainerIncludTag,先调用setLable,然后doEndTag。doEndTag时,首先查找父标签,ContainerTag,然后从中得到view,我们再从view中得到具体化的内容,这边就是url,最后让这个页面包含这个url,pageContext.include,在之后的现实,就会显示出该url指向的内容。这样,当三条include自定义标签都处理完后,我们就在一个页面中,嵌入了三个子页面。
若当我们再要request Page2时,同样处理,只是有些已经初始化的东西,就不必再初始化了。