您的位置:首页 > 理论基础 > 计算机网络

Liferay 启动过程分析1-重定向到 http://host:port/c

2012-06-22 10:05 459 查看
前几天搞了一个BUG,吧精力耗尽,也激发了我对Liferay这个框架内部的探究欲望。所以这几天端午节准备对Liferay框架启动过程进行深入研究,来满足自己的好奇心。

当我们在地址栏中访问http://localhost:8080时,因为Liferay应用本质上也是一个web应用,所以它会去找ROOT应用的web.xml,因为定义了<welcome-file-list>:

<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>


所以,它会去找index.jsp:

...
<%
...
String redirect = null;

LayoutSet layoutSet = (LayoutSet)request.getAttribute(WebKeys.VIRTUAL_HOST_LAYOUT_SET);

if (layoutSet != null) {
long defaultPlid = LayoutLocalServiceUtil.getDefaultPlid(layoutSet.getGroupId(), layoutSet.isPrivateLayout());

if (defaultPlid != LayoutConstants.DEFAULT_PLID) {
Layout layout = LayoutLocalServiceUtil.getLayout(defaultPlid);

ServicePreAction servicePreAction = (ServicePreAction)InstancePool.get(ServicePreAction.class.getName());

ThemeDisplay themeDisplay = servicePreAction.initThemeDisplay(request, response);

redirect = PortalUtil.getLayoutURL(layout, themeDisplay);
}
else {
redirect = PortalUtil.getPathMain();
}
}
else {
redirect = PortalUtil.getHomeURL(request);
}

if (!request.isRequestedSessionIdFromCookie()) {
redirect = PortalUtil.getURLWithSessionId(redirect, session.getId());
}

response.setHeader(HttpHeaders.LOCATION, redirect);

response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
%>

<html>

<head>
<title></title>
<meta content="1; url=<%= redirect %>" http-equiv="refresh" />
</head>

<body onload="javascript:location.replace('<%= redirect %>')">

</body>

</html>


其中,最值得看的就是<body onload="javascript:location.replace...),它会在DOM树加载完毕之后触发,那么我们感兴趣的是,这个<%=redirect%>到底是什么呢?

寻找<%=redirect%>的值

为此,我们去看上面那段代码,因为第一次登录,所以什么用户信息都没有,所以实际上走的是以下的代码段:

else {
redirect = PortalUtil.getPathMain();
}


然后这段代码会调用PortalUtil中的:

public static String getPathMain() {
return getPortal().getPathMain();
}


然后调用PortalImpl类中的:

public String getPathMain() {
return _pathMain;
}

而这个_pathMain是由该类中以下代码提供的,在PortalImpl构造器中:

// Paths

_pathProxy = PropsValues.PORTAL_PROXY_PATH;

_pathContext = ContextPathUtil.getContextPath(PropsValues.PORTAL_CTX);
_pathContext = _pathProxy.concat(_pathContext);

_pathFriendlyURLPrivateGroup =
_pathContext + _PRIVATE_GROUP_SERVLET_MAPPING;
_pathFriendlyURLPrivateUser =
_pathContext + _PRIVATE_USER_SERVLET_MAPPING;
_pathFriendlyURLPublic = _pathContext + _PUBLIC_GROUP_SERVLET_MAPPING;
_pathImage = _pathContext + PATH_IMAGE;
_pathMain = _pathContext + PATH_MAIN;

// Groups

所以_pathMain为_pathContext+PATH_MAIN ,我们依次来解析:

解析 _pathContext:

对于_pathContext,它是ContextPathUtil.getContextPath(PropsValues.PORTAL_CTX);

其中PropsValues.PORTAL_CTX是:

public static final String PORTAL_CTX = PropsUtil.get(PropsKeys.PORTAL_CTX);


它会去找PropsKeys接口中的常量定义:

public static final String PORTAL_CTX = "portal.ctx";


然后找到并替换之后,去执行PropsUtil.get("portal.ctx");

public static String get(String key) {
return _instance._get(key);
}


它会访问

private String _get(String key) {
return _getConfiguration().get(key);
}

这段代码最终会访问配置文件,然后读取key-value对到Configuration中,我们在portal.properties中找到了portal.ctx的定义:

##
## Portal Context
##

#
# Specify the path of the portal servlet context. This is needed because
# javax.servlet.ServletContext did not have access to the context path until
# Java EE 5.
#
# Set this property if you deploy the portal to another path besides root.
#
portal.ctx=/

所以portal.ctx=/

解析PATH_MAIN:

它在Portal接口中有定义:

public static final String PATH_MAIN = "/c";


所以综上所述,在PortalImpl构造器中的_pathMain = _pathContext + PATH_MAIN="/"+"/c"="//c"

它就是<%=redirect%>的值。

所以当index.jsp中DOM树加载完毕之后,它会去执行:

<body onload="javascript:location.replace('//c')">


而对于location.replace(String)方法,它的作用是启动一个不可逆的重定向:参见下面这篇文章:

http://www.roseindia.net/javascript/javascript-location-replace.shtml

所以我们现在知道,在DOM树加载完毕后,它吧请求发送到了http://localhost:8080/c 这个位置。

之后的步骤见下一篇博客
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息