一、初始化流程
//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将它们处理的结果按特定布局进行显示。
|