一、初始化流程
//Servlet初始化
Pluto.PortalImpl.Servlet.init()
// ServiceManager初始化
ServiceManager.init()
ConfigService.init() // 配置服务
LogService.init() // 日志服务
FactoryManagerService.init() // 工厂管理器
PortletDefinitionRegistryService.init() // Portlet定义注册表
PortletEntityRegistryService.init() // Portlet实体注册表
PageRegistryService.init() // Page注册表
//注,以上服务都读取同名的properties配置文件.
// 初始化Portlet容器, 容器实现类在ConfigService.properties中指定
PortletContainerFactory.getPortletContainer().init()
二、请求处理流程
Pluto.PortalImpl.Servlet.doGet()
1. 创建PortalEnvironment;
2. 查找ActionWindow;
2a. 如找到ActionWindow, 则为Action
执行PortletContainer.processPortletAction();
重定向输出.
2b. 找不到ActionWindow, 则为Render, 读取Page定义。
RootFragment root = PageRegistry.getRootFragment();
root.service(servletRequest, servletResponse);
3. 处理完毕;
// 处理Fragment, RootFragment与Pageregistry.xml文件关联, 后者定义了页面的布局
Pluto.portalImpl.Aggregation.RootFragment.service()
// 服务前置处理。
1. preService(request, response);
// 包含与当前fragment同名的jsp文件,当前为RootFragment。
2. RequestDispatcher rd = getServletConfig().getServletContext().
getRequestDispatcher(BASE_ROOT+jspName);
rd.include(request, response);
// 服务后置处理
3. postService(request, response);
// Pageregistry.xml
〈portal〉 // 对应RootFragment
〈fragment name="navigation"
class="org.apache.Pluto.portalImpl.aggregation.navigation.TabNavigation"〉
〈/fragment〉
〈fragment name="test" type="page"〉 // 对应PageFragment
〈navigation〉
〈title〉Test〈/title〉
〈description〉...〈/description〉
〈/navigation〉
〈fragment name="row" type="row"〉 // 对应RowFragment
〈fragment name="col1" type="column"〉 // 对应ColumnFragment
〈fragment name="p1" type="portlet"〉 // 对应PortletFragment
〈property name="portlet" value="3.1"/〉
〈/fragment〉
〈fragment name="p2" type="portlet"〉 // 对应PortletFragment
〈property name="portlet" value="4.1"/〉
〈/fragment〉
〈/fragment〉
〈/fragment〉
〈/fragment〉
〈/portal〉
// 上面的层次结构十分清楚,其中fragment与Fragment的子类对应,上面的定义中包括RootFragment,
PageFragment, RowFragment, ColumnFragment和PortletFragment,除了PortletFragment外,
其它Fragment的处理大致上是一样的,
Iterator childIterator = fragment.getChildFragments().iterator();
// 遍历子fragment, 并调用其服务方法。
while (childIterator.hasNext()) {
Fragment subfragment = (Fragment)childIterator.next();
if (subfragment instanceof AbstractNavigationFragment)
{
subfragment.service(request, response);
break;
}
}
三、Portal处理流程
先来看看Portlet的初始化, 主要是从配置文件中读取Portlet定义。
PortletFragment.init()
// 读取Portlet的实体Id, 在pageregistry.xml中由portlet属性指定.
String portletEntityId = getInitParameters().getString("portlet");
// 读取Portlet实体. portlet实体在portletentityregistry.xml中定义.
PortletEntity portletEntity = PortletEntityRegistry.getPortletEntity(...);
// portletentityregistry.xml
〈portlet-entity-registry〉
〈application id="3"〉 // 对应PortletApplicationEntity
〈definition-id〉testsuite〈/definition-id〉
〈portlet id="1"〉 // 对应PortletEntity
〈definition-id〉testsuite.TestPortlet1〈/definition-id〉
〈preferences〉
〈pref-name〉TestName4〈/pref-name〉
〈pref-value〉TestValue4〈/pref-value〉
〈read-only〉true〈/read-only〉
〈/preferences〉
〈/portlet>
〈/application>
〈application id="4"〉
〈definition-id>testsuite〈/definition-id〉
〈portlet id="1"〉
〈definition-id>testsuite.TestPortlet2〈/definition-id〉
〈preferences〉
〈pref-name〉TestName4〈/pref-name〉
〈pref-value〉TestValue4〈/pref-value〉
〈read-only〉true〈/read-only〉
〈/preferences〉
〈/portlet〉
〈/application〉
〈/portlet-entity-registry〉
//要注意这里的applicationid和portletid与pageregistry中的portletid的对应关系。
// Portlet服务
PortletFragment.service()
//load protlet
PortletContainer.portletLoad(...)
// 1.取得PortletDefinition, 从portletentityregistry中定义的application中读取portlet定义.
PortletDefinition def = portletWindow.getPortletEntity().getPortletDefinition();
// portlet.xml
〈portlet-app〉 // 对应PortletApplicationDefinition
〈portlet〉 // 对应PortletDefinition
〈description〉TestSuiteDescription〈/description〉
〈portlet-name〉TestPortlet1〈/portlet-name〉
〈display-name〉Test Portlet #1〈/display-name〉
〈portlet-class〉org.apache.Pluto.portalImpl.portlet.TestPortlet〈/portlet-class〉
〈init-param>
〈name〉config〈/name〉
〈value〉/WEB-INF/testsuite-config.xml〈/value〉
〈/init-param〉
〈supports〉
〈mime-type〉text/html〈/mime-type〉
〈portlet-mode〉VIEW〈/portlet-mode〉
〈portlet-mode〉EDIT〈/portlet-mode〉
〈portlet-mode〉HELP〈/portlet-mode〉
〈/supports〉
〈portlet-info〉
〈title〉Test Portlet #1〈/title〉
〈short-title〉Test #1〈/short-title〉
〈keywords〉Test,Testing〈/keywords〉
〈/portlet-info>
〈security-role-ref〉
〈role-name〉PlutoTestRole〈/role-name〉
〈role-link〉tomcat〈/role-link〉
〈/security-role-ref〉
〈/portlet〉
〈portlet-app〉
// 2.取得PortletInvoker
PortletInvoker invoker = PortletInvokerAccess.getPortletInvoker(def);
// 3.执行load操作
invoker.load(renderRequest, renderResponse)
// render Portlet
PortletContainer.renderPortlet(...);
// 1. 取得PortletInvoker
PortletInvoker invoker = PortletInvokerAccess.getPortletInvoker(...);
// 2. 执行render操作。
invoker.render(renderRequest, renderResponse);
// 处理Title, support modes,
// Portlet调用.
ProtletInvoker.invoke(...)
// 取得Portlet应用的dispatcher.
ServletDefinition servletDefinition = portletDefinition.getServletDefinition();
ServletContext servletContext = servletConfig.getServletContext();
RequestDispatcher dispatcher = servletDefinition.getRequestDispatcher(servletContext);
// 设置属性, METHOD_ID为别对应load, render和action。
servletRequest.setAttribute(Constants.METHOD_ID, methodID);
servletRequest.setAttribute(Constants.PORTLET_REQUEST, portletRequest);
servletRequest.setAttribute(Constants.PORTLET_RESPONSE, portletResponse);
// 调用Portlet
dispatcher.include(servletRequest, servletResponse);
四、Portlet处理流程
在Portlet应用的web.xml中,定义了PortletServlet为Portlet的Servlet,它由dispatch方法统一进行请求处理.
PortletServlet.dispatch(...)
// 设置portletConfig.
request.setAttribute(org.apache.Pluto.Constants.PORTLET_CONFIG, portletConfig);
Integer method_id = (Integer)request.getAttribute(Constants.METHOD_ID);
if (method_id == Constants.METHOD_RENDER)
{
renderRequest = (RenderRequest)request.getAttribute(Constants.PORTLET_REQUEST);
renderResponse = (RenderResponse)request.getAttribute(Constants.PORTLET_RESPONSE);
// prepare container objects to run in this webModule
prepareRenderRequest(renderRequest, request);
prepareRenderResponse(renderResponse, request, response);
portletClass.render(renderRequest,renderResponse);
}
else if (method_id==org.apache.Pluto.Constants.METHOD_ACTION)
{
actionRequest = (ActionRequest)request.getAttribute(Constants.PORTLET_REQUEST);
actionResponse = (ActionResponse)request.getAttribute(Constants.PORTLET_RESPONSE);
// prepare container objects to run in this webModule
prepareActionRequest(actionRequest, request);
prepareActionResponse(actionResponse, request, response);
portletClass.processAction(actionRequest,actionResponse);
}
else if (method_id == org.apache.Pluto.Constants.METHOD_NOOP)
{
//nothing to do
}
//注: portletClass即为portlet的具体实现类。
至此,请求就由portlet进行处理了。
从上面的流程可以看出,Pluto就是将请求分派到页面上的各个portlet,portlet根据method执行相应操作,
最后由Pluto将它们处理的结果按特定布局进行显示。