1. 系统启动
a) 说明:Tapestry启动时,采用的仍然是典型的HttpSerlvet的启动模式。在初始化的时候,他将加载用户定义的hivemodule.xml文件,并利用ApplicationInitializer存储整个Web应用的上下文,例如ServletContext等。在完成了上述初始化工作以后,将加载ServletRequestServicer,用于处理后续的http请求。
b) 流程图:
c) 代码:
i. contructRegistry()
protected Registry constructRegistry(ServletConfig config){
String name = config.getServletName();
ServletContext context = config.getServletContext();
addModuleIfExists(builder, context, "/WEB-INF/" + name + "/hivemodule.xml");
addModuleIfExists(builder, context, "/WEB-INF/hivemodule.xml");
return builder.constructRegistry(Locale.getDefault());
}
注:上述代码主要完成的工作就是加载用户定义的hivemodule.xml文件。
2. ApplicationInitializer
a) 说明:ApplicationInitializer采用的是Command模式,她主要负责加载Tapestry运行时的上下文。ApplicationInitializer的定义在tapestry.init.xml中。
b) 定义:
<contribution configuration-id="ApplicationInitializers">
<command id="WebContextInitializer" object="service:WebContextInitializer"
before="*"/>
<command id="ApplicationSpecificationInitializer"
object="service:ApplicationSpecificationInitializer"/>
</contribution>
c) 代码:
i. WebContextInitializer.initialize()
public void initialize(HttpServlet servlet){
ServletContext servletContext = servlet.getServletContext();
WebContext context = new ServletWebContext(servletContext);
_globals.storeServletContext(servletContext);
_globals.storeWebContext(context);
}
注:上述代码主要是把ServeltContext等保存在Tapestry的全局注册表当中。
ii. ApplicationSpecificationInitializer.initialize()
public void initialize(HttpServlet servlet){
IApplicationSpecification spec = null;
Resource specResource = findApplicationSpecification(servlet);
if (specResource == null){
spec = constructStandinSpecification(servlet);
}else
spec = _parser.parseApplicationSpecification(specResource);
_globals.storeActivator(new HttpServletWebActivator(servlet));
_globals.storeSpecification(spec);
}
注:上述代码主要是负责加载Tapestry的.application文件。
3. 请求处理—第一阶段
a) 说明:由于Tapestry采用的还是HttpServlet的模式,所以,他的入口仍然是继承自HttpServlet的ApplicationServlet。
在ServletRequestServer内部,她主要完成的是把原有的HttpServletRequest和HttpServletResponse进行封装,转换为Tapestry内部使用的WebRequest和WebResponse,这样做的一个好处就是,使后续的代码不再依赖于底层所使用的HttpServlet,从而可以在一个完全的Tapestry框架内部进行操作。
在WebRequestServicer内部,他所做的就是获取一个IEngine实例。而IEngine实例则是由EngineManager负责进行创建和维护,这里EngineManager提供了一个缓存,缓存基于Locale完成,也就是说对应于来自不同Locale的请求,EngineManager都将返回一个新的IEngine实例。当IEngine实例返回以后,后续的请求将由IEngine负责进行处理。
b) 流程图:
c) 代码:
i. EngineManager. getEngineInstance()
public IEngine getEngineInstance(){
Locale locale = _localeManager.extractLocaleForCurrentRequest();
IEngine result = (IEngine) _enginePool.get(locale);
if (result == null)
result = _engineFactory.constructNewEngineInstance(locale);
return result;
}
注:上述代码用于返回基于Locale的IEngine实例。
4. 请求处理—第二阶段
a) 说明:从IEngine的service()方法开始,我们转入了Tapestry的请求处理过程。在service()方法内部,IEngine通过RequestCycleFactory的newRequestCycle()方法创建一个IRequestCycle实例。
在创建IRequestCycle之前,RequestCycleFactory通过extractParameters()和decodeParameters()来提取和分析URL当中的参数。其中decodeParameters()是使用ServiceEncoder的decode()方法进行提取。通过在hivemind.xml当中contribute不同的ServiceEncoder,我们可以参与整个URL参数的decode过程。这也是实现Perma Link的一般方法。
在参数解析和提取以后,Tapestry将根据之前的参数提取结果,获得当前应该使用的IEngineService,并调用其service()方法。Tapestry提供的IEngineService实现包括了DirectService,PageService等。
b) 流程图:
c) 代码:
i. RequestCycleFactory. extractParameters()
private QueryParameterMap extractParameters(WebRequest request){
QueryParameterMap result = new QueryParameterMap();
Iterator i = request.getParameterNames().iterator();
while (i.hasNext()){
String name = (String) i.next();
String[] values = request.getParameterValues(name);
if (values.length == 1)
result.setParameterValue(name, values[0]);
else
result.setParameterValues(name, values);
}
return result;
}
注:上述代码用于从WebRequest当中提取参数,负责提取URL当中“?”后面的部分。
ii. RequestCycleFactory.decodeParameters()
private void decodeParameters(String servletPath, String pathInfo, QueryParameterMap map){
ServiceEncodingImpl se = new ServiceEncodingImpl(servletPath, pathInfo, map);
for (int i = 0; i < _encoders.length; i++){
_encoders[i].decode(se);
if (se.isModified())
return;
}
}
注:这里利用ServiceEncoder来分析参数。