首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

liferay加载进程详解 转

2012-10-26 
liferay加载过程详解 转当用户在浏览器地址栏上输入http://localhost:8080/后,经过几次迭代,服务器最终处

liferay加载过程详解 转

当用户在浏览器地址栏上输入http://localhost:8080/后,经过几次迭代,服务器最终处理的是http://localhost:8080/c/portal/update,那当服务器收到/c/portal/update的请求后做了什么动作,最后是怎么向浏览器发送网页信息呢?

?

1. 首先MainServlet接收这个请求,然后传递到LayoutAction。(具体怎么传递后续会介绍到)
在struts-config.xml中有定义,表明有关"/portal/layout"的请求是由LayoutAction来处理的。而在tiles-def.xml中定义"/portal/layout"最终传递到"/portal/layout.jsp"。

struts-config.xml
------------------------
<action path="/portal/layout" type="com.liferay.portal.action.LayoutAction">
? <forward name="portal.layout" path="portal.layout" />
</action>

tiles-def.xml
------------------
<definition name="portal.layout" extends="portal">
<put name="content" value="/portal/layout.jsp" />
?<put name="selectable" value="true" />
</definition>

2. 下面分析LayoutAction的简要流程

LayoutAction.execute()
--------------------------------
ThemeDisplay themeDisplay = (ThemeDisplay)req.getAttribute(WebKeys.THEME_DISPLAY);
Layout layout = themeDisplay.getLayout();

/* 加入/html/portal/layout/view/portlet.jsp 到网页*/
incluldeLayoutContent(req, res, themeDisplay, layout);

/* 加入/html/portal/layout.jsp 到网页,先portlet.jsp,后layout.jsp*/
return mapping.findForward("portal.layout");

LayoutAction.includeLayoutContent()
-----------------------------------------------------
String path = StrutsUtil.TEXT_HTML_DIR;
/* path = "/html" */

path += PortalUtil.getLayoutViewPage(layout);
/* path = "/html/portal/layout/view/portlet.jsp" */

RequestDispatcher rd = ctx.getRequestDispatcher(path);
rd.include(req, stringServletRes);

可见两个jsp文件是页面的关键所在。

/portal/layout/view/portlet.jsp
-----------------------------------------
<%
String content = LayoutTemplateLocalUtil.getContent(layoutTypePortlet.getLayoutTemplateId(),
???false, theme.getThemeId());
%>
<%= RuntimePortletUtil.processTemplate(application, request, response, pageContext, content) %>

/*****************************************************
其中content的内容通过断点调试可以知道(是什么时候生成的呢?)
<div id="content-wrapper">
? <table id="layout-grid">
??? <tr>
????? <td id="column-1" valign="top">
??????? $processor.processColumn("column-1")
????? </td>
????? <td id="column-2" valign="top">
??????? $processor.processColumn("column-2")
????? </td>
??? </tr>
? </table>
</div>
*****************************************************/
/* RuntimePortletUtil.processTemplate()函数返回的是一个很长很长的字符串,就是最终用于显示页面上各个portlet的代码,下面有分析 */

RuntimePortletUtil.processTemplate()
------------------------------------------------------
TemplateProcessor processor = new TemplateProcessor(ctx, req, res, portletId);
VelocityContext vc = new VelocityContext();
vc.put("processor", processor);
// Velocity variables
VelocityVariables.insertVariables(vc, req);
vc.put("taglibLiferay", velocityTaglib);
vc.put("theme", velocityTaglib);
StringWriter sw = new StringWriter();
Velocity.evaluate(vc, sw, RuntimePortletUtil.class.getName(), content);

String output = sw.toString();
/*****************************************************
output的初始内容为:
<div id="content-wrapper">
? <table id="layout-grid">
??? <tr>
????? <td id="column-1" valign="top">
??????? [$TEMPLATE_COLUMN_column-1$]
????? </td>
????? <td id="column-2" valign="top">
??????? [$TEMPLATE_COLUMN_column-2$]
????? </td>
????? <td id="column-3" valign="top">
??????? [$TEMPLATE_COLUMN_column-3$]
????? </td>
??? </tr>
? </table>
</div>
*****************************************************/

Map columnsMap = processor.getColumnsMap();

while (itr.hasNext()) {
? Map.Entry entry = (Map.Entry)itr.next();
? String key = (String)entry.getKey();
? String value = (String)entry.getValue();
? output = StringUtil.replace(output, key, value);
}

/*****************************************************
如果首页面上有四个portlet,名字为A,B,C,D,其中A在左边一列上,B,C同在中间一列,D在右边一列。则output的内容为:
<div id="content-wrapper">
? <table id="layout-grid">
??? <tr>
????? <td id="column-1" valign="top">
??????? <div id="layout-column_column-1">
????????? [$TEMPLATE_PORTLET_A$]
??????? </div>
????? </td>
????? <td id="column-2" valign="top">
??????? <div id="layout-column_column-2">
????????? [$TEMPLATE_PORTLET_B$]
????????? [$TEMPLATE_PORTLET_C$]?
??????? </div>
????? </td>
????? <td id="column-3" valign="top">
??????? <div id="layout-column_column-3">
????????? [$TEMPLATE_PORTLET_D$]?
??????? </div>
????? </td>
??? </tr>
? </table>
</div>
*****************************************************/

Map portletsMap = processor.getPortletsMap();
itr = portletsMap.entrySet().iterator();
while (itr.hasNext()) {
? StringMaker sm = new StringMaker();
? processPortlet(sm, ctx, req, res, portlet, queryString, columnId, columnPos,columnCount, null);
? output = StringUtil.replace(output, "[$TEMPLATE_PORTLET_" + portlet.getPortletId() + "$]", sm.toString());

/*****************************************************
? 这里每迭代一个portlet,output的内容中就添加了该portlet的view.jsp代码段落,而且还会增加portlet的标准头部和边框,如最小化,关闭等按钮及其对应的JavaScript代码。
*****************************************************/
}

return output;
/* 这个output就是在portlet.jsp中要显示的内容 */


portal.jsp
------------
<c:choose>
? <c:when test="<%= themeDisplay.isStateExclusive() %>">
??? <%= request.getAttribute(WebKeys.LAYOUT_CONTENT) %>
? </c:when>
? <c:when test="<%= themeDisplay.isStatePopUp() %>">
??? <liferay-theme:include page="portal_pop_up.jsp" />
? </c:when>
? <c:otherwise>
??? <liferay-theme:include page="portal_normal.jsp" />
? </c:otherwise>
</c:choose>

在Liferay中没有发现portal_normal.jsp的踪影,发现portal_normal.vm似乎有点相关。portal_normal粉墨登场。

portal_normal.vm
-------------------------
#parse ($init)
<html dir="#language ("lang.dir")">
<head>
? <title>$company_name - $the_title</title>
??? $theme.include($top_head_include)
??? #css ($css_main_file)
??? #js ($js_main_file)
??? #if ($company_logo != "")
????? <style type="text/css">
??????? #banner .logo {background: url($company_logo) no-repeat;
?????????????? height: ${company_logo_height}px;
?????????????? width: ${company_logo_width}px; }
????? </style>
??? #end
</head>

<body href="$update_available_url">#language("updates-are-available-for-liferay")</a>
????????? </div>
??????? #end
??????? #if ($has_navigation)
????????? #parse ("$full_templates_path/navigation.vm")
??????? #end
????? </div>
??? </div>

??? #if ($selectable)
????? $theme.include($content_include)
??? #else
????? <div id="content-wrapper" %>
<%@ include file="/html/common/themes/top_js-ext.jsp" %>
portal/portal-web/docroot/html/common/themes/top_js.jspf
<%
? String[] javaScriptFiles = PropsUtil.getArray(PropsUtil.JAVASCRIPT_FILES);
? for (int i = 0; i < javaScriptFiles.length; i++) {
%>
<script src="<%= themeDisplay.getPathJavaScript() %>/<%= javaScriptFiles[i] %>"?type="text/javascript"></script>
<%
}
%>

那javascriptFiles又如何得到的呢?

portal.properties
------------------------
javascript.files=\
??????? jquery/jquery.js,\
??????? jquery/cookie.js,\
?????
??????? jquery/tabs.js,\
??????? \
??????? liferay/liferay.js,\
??????? liferay/browser.js,\
??????? liferay/util.js,\
??????? liferay/language.js,\
??????? liferay/layout.js,\
??????? \
??????? liferay/ajax.js,\
??????? liferay/animate.js,\
??????? liferay/auto_fields.js,\
??????? liferay/color_picker.js,\
??????? liferay/columns.js,\
??????? liferay/dock.js,\
??????? liferay/dynamic_select.js,\
??????? liferay/freeform.js,\
??????? liferay/layout_configuration.js,......

另外还有一个很重要的properties文件值得关注:language.properties。好累啊,还有很多细节可以继续挖掘,还涉及到Velocity的一些变量的操作,休息下先。

?

热点排行