这个图显示了在数据库集群环境下的jetspeed集群配置,数据库负载均衡器实现数据库集群的单一影像,例子有weblogic server中的multipool datasource,sql server 基于的windows 2000集群的单一集群IP,ORACLE RAC 的支持多连接地址的thin jdbc driver。
3.4 Jetspeed的Session数据
支持集群必须使得各个服务实体针对某个任务的执行环境是相同的,对于jetspeed来说就是针对各个URL请求,session的数据能在各个 jetspeed上复制。这些session被同一个sessionid所标识,这些标识可能来自浏览器的cookies或URL中。我们首先用一个 velocityportlet来显示Jetspeed的session中到底保存了什么数据,这个portlet的注册名字为 SessionPortlet。
3.4.1 SessionPortlet
SessionPortlet是一个velocityPortlet,其类名可以是CustomizerVelocityPortlet或 VelocityPortlet,一般情况下没有必要开发一个新的portlet class。关于如何开发部署portlet的教程可见参考部分,现在我们分注册、控制助手、portlet模版和运行来讲述这个portlet。
3.4.1.1 注册
SessionPortlet用于显示目前的session数据。它在xreg中的注册代码为:
parent="CustomizerVelocity" application="false">
check infomation in session
org.apache.jetspeed.portal.portlets.CustomizerVelocityPortlet
cachedOnName="true" cachedOnValue="true"/>
hidden="true" cachedOnName="true" cachedOnValue="true"/>
legend
velocity.legend
3.4.1.2 控制助手Action
portlets.SessionAction是Velocityportlet模版portlet的控制助手,在velocity解释模版前执行:
public class SessionAction extends VelocityPortletAction {
protected void buildNormalContext( VelocityPortlet portlet,
Context context,
RunData rundata )
{
Map map = new HashMap();
Enumeration enumeration = rundata.getSession().getAttributeNames();
while (enumeration.hasMoreElements()) {
Object key = (Object) enumeration.nextElement();
Object value = (Object)rundata.getSession().getAttribute(key.toString());
map.put(key, value);
}
context.put("sessions",map);
}
}
从上面的代码可以看出,这个控制助手在模版的模型(MVC中的M)环境中设置了一个保存了session数据的map数据结构。
3.4.1.3 portlet模版
SessionPortlet的模版文件是session.vm(MVC中的V),这个文件的内容如下:
#foreach( $key in $sessions.keySet() )
- Key: $key -> Value: $sessions.get($key)
#end
3.4.1.4 定制psml和运行SessionPortlet
用admin/jetspeed或turbine/turbine帐号/口令登录到jetspeed系统后,可以在velocity.legend portlet分类中找到SessionPortlet,把它加入到你的psml中后可以看到SessionPortlet显示的session数据(你可以多多点击其它的URL,尽量地使jetspeed在session中多放一些数据):
从上面的session快照可以看出,Jetspeed的session数据主要分为两类:BaseJetspeedUser和JetspeedHttpStateManagerService$StateEntry,下面我们就分别来看看这两个类的情况。
3.4.2 BaseJetspeedUser
我们从《Session数据类图(部分)》可以看出BaseJetspeedUser实现了serializable接口。另外分析这个类及其父类的代码可了解到这个类的成员也实现了serializable接口。所以可以初步得出这个类是集群安全的。
DefaultTurbineRundata实现了这个类型的session数据的操作接口:
保存user对象到session中,这个方法登录后由TurbineAuthentication的login调用,登录前由 JetspeedSessionValidator的doPerform调用,它们同时会调用DefaultTurbineRundata的 setUser方法:
public void save()
{
session.putValue(User.SESSION_KEY, (Object) user );
}
public void setUser(User user)
{
this.user = user;
}
从session中获取user对象数据,这个方法由JetspeedSessionValidator的doPerform调用:
public void populate()
{
user = getUserFromSession();
if ( user != null )
{
user.setLastAccessDate();
user.incrementAccessCounter();
user.incrementAccessCounterForSession();
}
}
public User getUserFromSession()
{
return getUserFromSession(session);
}
public static User getUserFromSession(HttpSession session)
{
try
{
return (User) session.getValue(User.SESSION_KEY);
}
catch ( ClassCastException e )
{
return null;
}
}
删除session中的用户数据,目前没地方调用:
public boolean removeUserFromSession()
{
return removeUserFromSession(session);
}
public static boolean removeUserFromSession(HttpSession session)
{
try
{
session.removeValue(User.SESSION_KEY);
}
catch ( Exception e )
{
return false;
}
return true;
}