Terry.Li-彬

虚其心,可解天下之问;专其心,可治天下之学;静其心,可悟天下之理;恒其心,可成天下之业。

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  143 随笔 :: 344 文章 :: 130 评论 :: 0 Trackbacks
 

先前的文章提到/c/*的请求都是交给MainServlet处理的,现在分析对于不同的/c/*,例如/c/layout或者/c/update_layout等请求是怎么传递到不同的action去的呢。

下面以显示 Add Content 为例进行分析,Add Content 窗口其实是一个在 portlet-custom.xml 中定义的名为87的portlet。点击Add Content链接会产生一个Reqest,开始整个处理的流程。

1. Request的生成。

当时页面的源文件中有关的代码为:
<li class="add-content">
<a href="javascript: void(0);" onclick="LayoutConfiguration.toggle('10102', '87', '');">Add Content</a>
</li>

点击add content调用的是LayoutConfiguration.toogle()。

layout_configuratioin.js
var LayoutConfiguration = {
  toggle : function (plid, ppid, doAsUserId) {
  var url = themeDisplay.getPathMain() + "/portal/render_portlet?p_l_id=" + plid + "&p_p_id=" +ppid + "&doAsUserId=" + doAsUserId + "&p_p_state=exclusive";
  AjaxUtil.update(url, popup, {onComplete: function(){
               LayoutConfiguration.init();
               Liferay.Util.addInputType();
               Liferay.Util.addInputFocus();}
  });};
  /*总之是会生成一个Ajax请求发送到服务器,过程以后可以分析 */

用Wireshark捕捉到的Request数据如下,知道请求中含有/c/portal/render_portlet字段,那自然会送入 MainServlet处理了。

2. MainServlet.service()

/* 这里是Request首先到达的地方*/

ServletContext ctx = getServletContext();
req.setAttribute(WebKeys.CTX, ctx);
PortletRequestProcessor portletReqProcessor = PortletRequestProcessor.getInstance(this, moduleConfig);
ctx.setAttribute(WebKeys.PORTLET_STRUTS_PROCESSOR, portletReqProcessor);
callParentService(req, res);
/* 调用ActionServlet.service(),由于在ActionServlet中没有覆盖service方法,所以 MainServlet 的super.service() 追溯到HttpServlet 的service方法 */

3. HttpServlet.service()

if (method.equals(METHOD_GET)) { ,,,
} else if (method.equals(METHOD_POST)) {
  doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
  doPut(req, resp); 
} else if (method.equals(METHOD_DELETE)) {
  doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
  doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
  doTrace(req,resp);
}

/* 在 service 中,根据http的类型,分别调用 doPost, doGet, doPut, ...,由于ActionServlet中实现了doPost等方法,所以MainServlet.service()方法会传递到 ActionServlet中的doPost等方法。*/

4. ActionServlet.doPost()

process(request, response);

/* 在另外ActionServlet的不同方法中,例如doGet(),doPut(),都调用了process()方法。*/


5. ActionServlet.process()

ModuleConfig config = getModuleConfig(request);
RequestProcessor processor = getProcessorForModule(config);
if (processor == null) {
  processor = getRequestProcessor(config);
}
processor.process(request, response);

/* 最终传递到对应的Request Processor 的process()方法中去,也就是PortalRequestProcessor.process() */


6. PortalRequestProcessor.process()

public void process(HttpServletRequest req, HttpServletResponse res)
  throws IOException, ServletException {
  String path = super.processPath(req, res); //path = “/portal/render_portlet”
  ActionMapping mapping = (ActionMapping)moduleConfig.findActionconfig(path);
  super.process(req, res);
  /*由于TilesRequestProcessor中没有定义process()方法,所以调用 RequestProcessor.process() */
}


7. RequestProcessor.process()

public void process(HttpServletRequest request, HttpServletResponse response)
  throws IOException, ServletException {

  String path = processPath(request, response);
  //这里path = “/portal/render_portlet”.

  ActionMapping mapping = processMapping(request, response, path);
  //这里找到在struts-config.xml中定义的关于上面path的mapping.

  Action action = processActionCreate(request, response, mapping);
  //这里生成了RenderPortletAction.

  ActionForward forward = processActionPerform(request, response, action, form, mapping);

  processForwardConfig(request, response, forward);
}

至此,每个由 MainServlet 传递来的 Request 都能到达对应的 Action,例如 LayoutAction,RenderPortletAction,UpdateLayoutAction,由这些 Action 最终完成 Layout 和 Portlet 的呈现。这里对应的action是RenderPortletAction(由下面的struts-config.xml中定义)。

下面以RenderPortletAction为例说明进一步的action过程。在struts-config.xml这个文件中定义了action class, forward path。

<action path="/portal/layout" type="com.liferay.portal.action.LayoutAction">
  <forward name="portal.layout" path="portal.layout" />
</action>

<action path="/portal/update_layout" type="com.liferay.portal.action.UpdateLayoutAction" />

<action path=“/portal/render_portlet” type=“com.liferay.portal.action.RenderPortletAction”>
  <forward name=“/portal/render_portlet” path=“/portal/render_portlet.jsp”/>
</action>
<!-- 这里定义了由RenderPortletAction来处理”/portal/render_portlet”,而且最后要forward到” /portal/render_portlet.jsp”。所以最后会把render_portlet.jsp包含到response的页面当中-- >

那render_portlet.jsp又是如何实现最终把add content这个portlet显示出来的呢,下回接着分析。


 

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2177383

posted on 2008-03-14 14:12 礼物 阅读(1162) 评论(0)  编辑  收藏 所属分类: Liferay