Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103753223
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: LINUX

2008-04-23 21:19:40

出处:ChinaITLab  
 
3.4.2.1 用户登录
用户在jetspeed的首页中输入用户名和口令,接着点击登录(login)按钮,可以激活JLoginUser.doPerfom-> TurbineAuthentication.login->DefaultTurbineRundata.save->JetspeedSessionValidator.doPerform-> DefaultTurbineRundata.populate系列步骤。
如果properties配置中的配置项 automatic.logon.enable 的值为true,JLoginUser.doPerfom还会设置浏览器cookies:username 和logincookie。username是成功登录的用户名, logincookie是一个随机值,会保存到用户数据库中。
当用户访问jetspeed的首页时,JetspeedSessionValidator.doPerform检查RunData对象中的当前用户,如果没有登录而且automatic.logon.enable 的值为true,它会从cookies中获取username 和logincookie,再从用户数据库中查寻用户的logincookie,如果它们相等则调用下面的代码设置RunData的用户数据:
data.setUser(user);
user.setHasLoggedIn(new Boolean(true));
user.updateLastLogin();
data.save();
至于针对不同的用户,首页中显示的portlet由缺省screen模版中调用JetspeedTool的方法(有一套PSML定位算法)来决定。
3.4.2.2 当session过期之后显示匿名用户的主页
当session过期,Turbine.doget首先会创建新的session,接着激活 JetspeedSessionValidator.doPerform-> JetspeedSecurity.getAnonymousUser->DefaultTurbineRundata.save系列步骤。
JetspeedSessionValidator.doPerform会设置缺省screen模版。
3.4.2.3 用户登出
当用户登录之后,点击Jetspeed系统右上角的登出(logout)按钮,可以激活JLogOut.doPerform-> TurbineAuthentication.logout-> TurbineAuthentication.getAnonymousUser-> DefaultTurbineRundata.save系列步骤。
TurbineAuthentication.getAnonymousUser从数据库中得到匿名用户的用户数据(根据properties配置中user.anonymous项)。
如果properties配置中配置项automatic.logon.enable 的值为true,JLogOut.doPerform还会删除浏览器和当前request的cookies:username 和logincookie,防止后面的JetspeedSessionValidator拿着先前的用户数据自动登录。 JLogOut.doPerform最后设置data的缺省screen模版。
3.4.3 JetspeedHttpStateManagerService$StateEntry
我们从《Session数据的类图(部分)》可以看出StateEntry没有实现了Serializable接口。把它放到session的属性中不是集群安全的。Serializable接口只是个标志接口,它不拥有任何函数和数据成员,
为了使其集群安全化,首先必须让StateEntry实现Serializable接口。
DefaultJetspeedRunData拥有下列对StateEntry类型的session数据操作接口:
用户session接口,获取保存用户session数据的SessionState。这个SessionState保存的session数据以 "org.apache.jetspeed.services.statemanager.JetspeedHttpStateManagerService"+ sessionID为key。
public SessionState getUserSessionState()
{
StateManagerService service = (StateManagerService)TurbineServices
.getInstance().getService(StateManagerService.SERVICE_NAME);
if (service == null) return null;
return service.getSessionState(getSession().getId());
}
request的Session接口,获取保存当前request session数据的SessionState。这个SessionState保存的session数据以 "org.apache.jetspeed.services.statemanager.JetspeedHttpStateManagerService"+ (sessionID和profileID组成的pageSessionID)为key。
public SessionState getPageSessionState()
{
StateManagerService service = (StateManagerService)TurbineServices
.getInstance().getService(StateManagerService.SERVICE_NAME);
if (service == null) return null;
return service.getSessionState(getPageSessionId());
}
Portlet的Session接口,获取保存Portlet session数据的SessionState。这个SessionState保存的session数据以 "org.apache.jetspeed.services.statemanager.JetspeedHttpStateManagerService"+ pageSessionID+portletID为key。
public SessionState getPortletSessionState(String id)
{
// get the StateManagerService
StateManagerService service = (StateManagerService)TurbineServices
.getInstance().getService(StateManagerService.SERVICE_NAME);
if (service == null) return null;
String pageInstanceId = getPageSessionId();
return service.getSessionState(pageInstanceId + id);
}
3.4.3.1 类图
 

BaseStateManagerService有一个类型为Map的成员变量m_httpSessions,以Thread对象为key, HttpSession对象为值。HttpSession对象中属性的key 是前面DefaultJetspeedRunData的StateEntry类型的session数据操作接口的key,属性的值为StateEntry 对象。StateEntry对象的成员变量m_key保存操作接口的key,成员变量m_map是一个Map对象,以后面我们要讲的 setAttribute方法的name参数为 key,value参数为值。
3.4.3.2 初始化
下面的顺序图是一个简图,主要用于解释BaseStateManagerService的成员变量m_httpSessions的映射如何被填充和清除。
 

Turbine是一个servlet,其doGet方法是jetspeed系统的入口。
填充
Turbine请求JetspeedRunDataService生成RunData对象,JetspeedRunDataService调用 HttpServiceRequest的getSession(true)方法获取与当前请求对应的httpSession对象(以true为参数, getSession在当前session无效时会返回一个新的httpSession对象,否则返回先前请求的httpSession对象), JetspeedRunDataService接着调用JetspeedHttpStateManagerService的 setCurrentContext(httpSession对象)方法,这个方法会以当前的Thread为key,参数httpSession对象为值填充BaseStateManagerService的成员变量m_httpSessions。
清除
doGet方法填充了m_httpSessions,并作了好多事情之后,在即将退出之前调用了JetspeedRunDataService的 putRunData(data)方法,这个方法再调用JetspeedHttpStateManagerService的 clearCurrentContext()方法删除BaseStateManagerService的成员变量m_httpSessions中以当前 Thread为key的Map项。
下图显示了m_httpSessions对象经过初始化后的内存状态快照,体现了m_httpSessions对象保留的Thread-〉HttpSession的映射关系。
 

3.4.3.3 属性操作
当DefaultJetspeedRunData通过session操作接口获取SessionState之后,其它就可以使用SessionState对象的成员方法操作状态属性了。这两个方法是:
public void setAttribute( String name, Object value );
public void removeAttribute( String name );
 

在从RunData对象处获取sessionState对象后,jetspeed代码可以调用这个对象的属性操作方法。
setAttribute(name,value)操作的大概步骤是:
(1) 主要步骤:
1.1sessionState对象利用自己的key,结合参数name,value调用JetspeedHttpStateManagerService的setAttribute(key,name,value)方法;
1.1.1JetspeedHttpStateManagerService调用自己的getState(key)方法在参数key的帮助下获取保存在当前线程session中的StateEntry对象的m_map变量,这个过程由1.1.1.1-1.1.1.4组成;
1.1.2得到StateEntry对象的m_map变量后,JetspeedHttpStateManagerService接着先处理m_map中的先前的参数name对应的属性值,再设置参数name对应的属性值新值为参数value。
(2) 候选步骤:
1.1.1a 如果session中没有相应的StateEntry对象,则先生成并往一个session中加入一个。
getAttribute(name)操作的大概步骤是:
(1) 主要步骤:
2.1sessionState对象利用自己的key,结合参数name调用JetspeedHttpStateManagerService的getAttribute(key,name)方法;
2.1.1JetspeedHttpStateManagerService调用自己的getState(key)方法在参数key的帮助下获取保存在当前线程session中的StateEntry对象的m_map变量;
2.1.2得到StateEntry对象的m_map变量后,JetspeedHttpStateManagerService接着调用m_map对象的get(name)方法获取属性值。
下图体现了这些方法执行后HttpSession对象保留的key-> StateEntry对象以及StateEntry对象的Name->Value的映射关系。
 

3.5 修改建议
(1) 实现数据库形式的repository。根据前面的集群需求第五条,必须把repository数据库化才能使得集群下的各个jetspeed的资源视图相同。
(2) StateEntry。根据前面的集群需求第一条,必须让StateEntry实现Serializable接口。目前StateEntry是一个内部类,为了让JVM的Serializer设施能顺利创建StateEntry对象,最好把其public化。
(3) setAttribute要重设session属性。根据前面的集群需求第二条,session对象的setAttribute是导致复制的引子,我们必须在改变session属性后调用session对象的setAttribute方法重置session属性,如下图所示。
 

虽然Jetspeed中这样模式的代码如下:
更改JetspeedHttpStateManagerService的setAttribute方法。
对下面类中的doXXX方法按照这个模式进行修改。
controllers.MultiColumnControllerAction;
portlets.CustomizeSetAction;
controllers.RowColumnControllerAction;
注意StateEntry中的值的序列性。
4 总结
可以这样说,目前的jetspeed在设计和实现时没有考虑集群环境下的运行情况,本文的分析突出了jetspeed支持集群的主要症结、但不一定完善,甚至有不正确的地方,另外一个主要内容是分析jetspeed保存在session对象中的数据。希望本文有助于大家加深对集群的理解,有助于提醒大家在设计和开发软件系统时"keep clustering in mind"。
阅读(500) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~