Pluto控制流程

阅读更多


一、初始化流程

  //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将它们处理的结果按特定布局进行显示。

 

你可能感兴趣的:(Apache,XML,应用服务器,Servlet,配置管理)