一、初始化流程
? //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將它們處理的結果按特定布局進行顯示。
|