RO09 - RemObjects 2.0 Session
管理器
本文将说明
RemObjects SDK 2.0
的一个重要特性
: Session
管理器
.
Sessions
要写一个灵活的服务端首选途径是开发无状态实体
.
客户端不保持服务资源(如数据库连接)
,
调用完毕马上释放
.
这种方式也用在
Web
应用程序中
,
但是出现在
CS
架构中可以大家就比较陌生了
.
SessionServer
范例
SessionServer
范例非常简单
,
但是却展示如何执行常用的功能:授权登陆和只有登陆的用户才能成功调用开放的方法
.
这里提供两个服务
: LoginService
和
SessionService
.
LoginService
服务接口声明如下
:
LoginService = interface
[
'{A8C9C8A2-3988-4E92-8846-6CDE7B35AA1E}'
]
function
Login(const UserID: String; const Password: String): boolean;
procedure
Logout(const SessionID: String);
end
;
SessionService
服务接口声明如下
:
SessionService = interface
[
'{EE96A14F-A446-4194-A1FD-C4F900DFBE62}'
]
function
GetSessionValue(const Name: String): String;
procedure
SetSessionValue(const Name: String; const Value: String);
function
GetSessionID: String;
end
;
客户端首先调用
Login
方法传递用户
ID
和密码(本范例要求用户名和密码相等)
.
在
Login
之前调用
SessionService
服务将抛出异常
.
最后
,
如果客户端
5
分钟内没有请求服务
,Sessin
失效
,
下次请求需要再次登陆
.
RemObjects Session
管理器
Session
管理器的思想是使用数据快照保存一个服务对象,当用户调用服务器方法时从中获取信息
.
为了使用
RemObjects Session,
服务端对象必须从
TRORemoteDataModule
继承
. TRORemoteDataModule
已经在
RemObjects SDK 2.0
中扩展
,
增加了两个新的属性
: SessionManager
和
RequiresSession.
SessionManager
属性
这个属性必须在单例模式
(Singleton)
下使用
,
指向
SessionManager
控件
.
在
SessionManager
服务中要将这些控件放在主窗体中
.
保证他们唯一并已经实例化
现在在
SDK
中有两种类型的
Session
管理器
:
TROInMemorySessionManager
:
在服务执行程序内存中保存
Session
信息
,
速度快
,
但是不能长期保存
.
TROEventSessionManager
:
自定义
Session
管理器
,
允许将特殊的事件提供处理程序
,
如
CreateSession
和
DeleteSession.
具有很好的可配置性
,
可以保存
Session
信息
.
RequiresSession
属性
and DestroySession
方法
每个服务器端方法都是准备好被调用的
,RemObjects
引擎检查对象是否继承了
IROObjectActivation
接口
,
如果是
,
则在方法调用前都会触发
DoActivate
方法
,
调用后触发
DoDeactivate
方法
..
TRORemoteDatamodule
继承了
IROObjectActivation,
在
DoActivate
及
DoDeactivate
中获取和释放
Session.
为了控制
Session
的获取和释放
,
需要使用
RequiersSessoin
属性和
DestroySession
方法
.
RequiresSession
属性通知服务端对象是否允许创建新的
Session
或是否要使用以及存在的
Session.
一般在象
Login
方法中需要新建一个
Session,
而在其它的调用中只需用使用存在的
Session.
而
DestroySession
则通知服务端对象从
Session
列表中删除一个
Session.
下面是
TRORemoteDataModule.DoOnActivate
方法的代码
(unit uRORemoteDataModule.pas):
procedure TRORemoteDataModule.DoOnActivate(aClientID: TGUID);
begin
fSession := fSessionManager.FindSession(aClientID);
if (fSession=NIL) then begin
if RequiresSession then
RaiseError(err_SessionNotFound, [GUIDToString(aClientID)])
else
fSession := fSessionManager.CreateSession(aClientID);
end;
end;
从中可见如果
RequiresSession
为
True
并且需要的
Session
没有发现服务端将会抛出异常
.
对应的方法执行完毕后将调用
DoDeactivate:
procedure
TRORemoteDataModule.DoOnDeactivate(aClientID: TGUID);
begin
[..]
if
fDestroySession then
fSessionManager.DeleteSession(fSession.SessionID, FALSE)
else
fSessionManager.ReleaseSession(fSession);
end
;
LoginService
编程
你将发现在
RemObjects SDK
中实现一个
Login
服务是多么简单
.
注意
LoginService
的
RequiresSession
属性设置为
False.
function
TLoginService.Login(const UserID: String;
const Password: String): boolean;
begin
result := (UserID=Password);
if not
result then DestroySession;
// Informs the SessionManager to discard the session because the login failed
end
;
procedure
TLoginService.Logout(const SessionID: String);
begin
DestroySession;
// Discards the session
end
;
SessionService
编程
下面的代码向你展示如何在其它的服务中使用
Session.
注意
:SessionService
的
RequiresSession
属性设置为
True.
function
TSessionService.GetSessionValue(const Name: String): String;
begin
result := Session.Values[Name]
end
;
procedure
TSessionService.SetSessionValue(const Name: String; const Value: String);
begin
Session.Values[Name] := Value
end
;
function
TSessionService.GetSessionID: String;
begin
result := GUIDToString(ClientID);
end
;