上回说到/c/portal/render_portlet请求经过MVC过程后会到达render_portlet.jsp。
render_portlet.jsp
-------------------------
Portlet portlet = (Portlet)request.getAttribute(WebKeys.RENDER_PORTLET);
cachePortlet = PortletInstanceFactory.create(portlet, application);
cachePortlet.render(renderRequestImpl, renderResponseImpl);
CachePortlet.render()
_invoke(req, res, false);
CachePortlet._invoke()
if (action)
_portlet.processAction(...)
else
_portlet.render(...);
//因为87 portlet是一个StrutsPortlet,在这里会调用StrutsPortlet.render()方法,由于StrutsPortlet和LiferayPortlet中都没有定义render()方法,最终调用的是GenericPortlet.render()方法。
GenericPortlet.render()
response.setTitle(getTitle(request));
doDispatch(request, response);
//由于LiferayPortlet中覆盖了doDispatch()方法,所以调用的是LiferayPortlet.doDispatch()
LiferayPortlet.doDispatch()
if (mode.equals(PortletMode.VIEW)) {
doView(req, res);
}
else if (mode.equals(LiferayPortletMode.ABOUT)) {
doAbout(req, res);
}
else if (mode.equals(LiferayPortletMode.CONFIG)) {
doConfig(req, res);
}
.......
//由于StrutsPortlet中重载了doView, doAbout等方法,所以调用的是StrutsPortlet中的各种doXXX()方法,下面以doView()为例
//另外有可能会有别的类型的portlet,例如liferay的JSPPortlet,从而会调用JSPPortlet.doXXX()方法。在JSPPortlet.doView中,调用include(viewJSP, req, res);而viewJSP = getInitParameter("view-jsp");所以在这个地方就可以把该JSPPortlet定义好的view.jsp直接include进来,没有如同StrutsPortlet的后续工作。
StrutsPortlet.doView()
include(req, res);
//StrutsPortlet中其他的doXXX()方法都会最后调用include()方法。
StrutsPortlet.include()
PortletRequestProcessor processor = _getPortletRequestProcessor(req);
processor.process(req, res);
PortletRequestProcessor.process(RenderRequest req, RenderResponse res)
//这里PortletRequestProcessor有两个process方法,一个处理RenderRequest,另一个处理ActionRequest。
HttpServletRequest httpReq = PortalUtil.getHttpServletRequest(req);
HttpServletResponse httpRes = PortalUtil.getHttpServletResponse(res);
process(httpReq, httpRes);
//由于PortletRequestProcessor和TilesRequestProcessor中都没有重载process(HttpServletReq, HttpServletRes),调用的是RequestProcessor的process()方法。
RequestProcessor.process(HttpServletRequest, HttpServletResponse)
String path = processPath(request, response); //这里是/layout_configuration/view
ActionMapping mapping = processMapping(request, response, path);
processForward(request, response, mapping)
processInclude(request, response, mapping)
ActionForward forward = processActionPerform(request, response, action, form, mapping);
……
protected void doInclude( String uri, HttpServletRequest request, HttpServletResponse response)
{
RequestDispatcher rd = getServletContext().getRequestDispatcher(uri);
rd.include(request, response);
}
portlet-custom.xml中定义了:
<portlet>
<portlet-name>87</portlet-name>
<display-name>Layout Configuration</display-name>
<portlet-class>com.liferay.portlet.StrutsPortlet</portlet-class>
<init-param>
<name>view-action</name>
<value>/layout_configuration/view</value>
</init-param>
.....
</portlet>
struts-config.xml中定义了action:
<action path="/layout_configuration/view" forward="portlet.layout_configuration.view" />
tiles-def.xml中定义了view.jsp:
<definition name="portlet.layout_configuration.view" extends="portlet.layout_configuration">
<put name="portlet_content" value="/portlet/layout_configuration/view.jsp" />
</definition>
最后完成了万里长征,到达了/layout_configuration/view.jsp。
/layouot_configuration/view.jsp
-------------------------------------------
<%
PortletCategory portletCategory = (PortletCategory)WebAppPool.get(String.valueOf(company.getCompanyId()), WebKeys.PORTLET_CATEGORY);
List categories = ListUtil.fromCollection(portletCategory.getCategories());
Collections.sort(categories, new PortletCategoryComparator(company.getCompanyId(), locale));
Iterator itr = categories.iterator();
while (itr.hasNext()) {
request.setAttribute(WebKeys.PORTLET_CATEGORY, itr.next());
%>
<liferay-util:include page="/html/portlet/layout_configuration/view_category.jsp" />
<%
}
%>
/layouot_configuration/view_category.jsp
-----------------------------------------------------------
<%
itr2 = portlets.iterator();
while (itr2.hasNext()) {
Portlet portlet = (Portlet)itr2.next();
divId = new StringMaker();
divId.append(newCategoryPath);
divId.append(":");
matcher = pattern.matcher(PortalUtil.getPortletTitle(portlet, application, locale));
while (matcher.find()) {
divId.append(matcher.group());
}
%>
<div class="layout_configuration_portlet" id="<%= divId %>">
<table border="0" cellpadding="2" cellspacing="0" width="100%">
<tr>
<td width="99%">
<%= PortalUtil.getPortletTitle(portlet, application, locale) %>
</td>
<td align="right">
<input type="button" value="<liferay-ui:message key="add" />"
onClick="addPortlet('<%= plid%>', '<%= portlet.getPortletId() %>', '<%= themeDisplay.getDoAsUserId() %>');
if (<%= !portlet.isInstanceable() %>) {
var div = document.getElementById('<%= divId %>');
div.parentNode.removeChild(div);
};"
>
</td>
</tr>
</table>
</div>
<%
}
%>
在view_category.jsp中列出了每个category中所包含的portlet列表,一旦点击了"add"按钮,会调用addPortlet()方法在页面上增加一个portlet。在view_category.jsp中还实现了输入关键字对portlet进行过滤的功能。