RO13 –
智能项目:使用
RemObjects SDK
创建可升级的
Smart Service
作者
Nathanial Woolls
RemObjects
提示
:
虽然我们相信本文档是正确的但是我们并不作保证
.
非常感谢本文的作者
.
本文向你展示创建你自己的
RemObjects Smart Service™
的步骤
,
通过标准的
SOAP
协议在
HTTP
通道发布业务逻辑服务
,
同时也支持其它方式
,
包括
RemObjects
高效的二进制流消息格式,与本地
DLL
一样的方式使用
ISAPI
服务传递数据
.
新的
RemObjects ISAPI
服务
启动
Delphi
后
,
点击
"File|New|Other",
打开
"New Project"
对话框
.
选择
"RemObjects SDK"
标签并选中
"ISAPI/NSAPI Server Project"
项
:
点击
“OK”
按钮
.
弹出一个
“RemObjects ISAPI/NSAPI Server Project”
设置窗口
.
填写参数如下
:
现在你已经生成了一个新的
RemObjects
服务项目
-SmartProject.
项目中包含一个
WebModule,
其中有
TROSOAPMessage
和
TROWebBrokerServer
控件
.
这是
RemObjects ISAPI
服务的基本内容
:
在
Delphi
的主菜单中点击
"RemObjects|Service Builder",
弹出
RemObjects Service Builder,
创建一个
Smart Service.
现在你需要花费一些时间去设计你的
RemObjects
服务了
:
新的
RemObjects
服务默认带有两个方法
Sum()
和
GetServerTime(),
下面的例子中我们会使用它们
.
现在点击
Delphi
主菜单的
"Project|Options".
在
"Project Options"
对话框中点击
"Directories/Conditionals"
标签在
"Output directory"
中输入
ISAPI
的目录
.
点
"OK"
按钮
.
假设你已经安装了
OnCompile Helpers,
点击
"Project|OnCompile Helpers|COM+|Manage COM+ Applications".
在
"Manage COM+ Applications & Services"
对话框中
,
选择在你的
ISAPI
目录中相应的
COM
应用程序并点击
"Set as Debug Host"
按钮
.
弹出
“Run Parameters”
对话框
,
输入参数并在
delphi IDE
中调试你的
ISAPI
服务
.
点击
OK
按钮
.
点击
Delphi IDE
工具栏中的
"Run"
按钮
. RemObjects
预编译器为你的
Web
服务生成一些必要的单元文件
(
除非你执行这些单元否则每次编译都回生成
):
现在打开
IE
浏览器输入你的
ISAPI Web
服务地址
.
本例是
http://localhost/isapi/SmartProject.dll/SOAP.
将会出现一个你所创建的
Web Service
的
WSDL
文档
.
回到你的项目
,
打开项目中的代码文件
.
会发现一个
SmartService_Impl.pas
文件
. uses SysUtils
后加入如下代码完善
Sum() and GetServerTime()
方法
(
蓝色的
):
function
TSmartService.Sum( const A: Integer; const B: Integer): Integer;
begin
Result := A + B;
end ;
function
TSmartService.GetServerTime: DateTime;
begin
Result := Now;
end ;
完成后编译服务
.
现在你已经创建好了一个功能完善的标准的
HTTP+SOAP
的
Web
服务
.
使用你的
Web Service
在项目管理窗口中右击项目组
,
点击
"Add New Project"
菜单项
.
选择
"New"
标签中的
"Application"
项
.
点击
OK
按钮
.
简单的设计主窗体如下所示
,
包含一个
Edit
控件
,
两个
Button
和一个
TROSoapMessage
控件
,
一个
TROWinInetHTTPChannel
控件
.Soap
消息控件用于我们的
Web
服务通讯
,WinInet
通道属于
HTTP
通道可以提供不受
RemObjects
的限制
(WinInet
是
Windows
特有的
,
但是它比其它的
HTTP
通道更灵活
).
在
"Project Manager"
中右击点击
"Add"
菜单项
.
选择在你的服务中生成的接口文件
.
本例是
SmartLibrary_Intf.pas.
你也可以使用
RemObjects Service
从你的服务发布的
WSDL
文件生成这个接口文件,但当你同时创建服务和客户端时这种方式是最方便的
.
按下
ALT+F11
键打开
"Use Unit"
对话框
.
将
"SmartLibrary_Intf"
单元添加到主窗体单元
:
给
Add
和
GetTime
按钮添加如下事件处理程序
:
procedure TForm2.Button1Click(Sender: TObject);
begin
ROWinInetHTTPChannel1.TargetURL := Edit1.Text;
with CoSmartService.Create(ROSOAPMessage1, ROWinInetHTTPChannel1) do
ShowMessage(IntToStr(Sum(
1
,
2
)));
end ;
procedure TForm2.Button2Click(Sender: TObject);
begin
ROWinInetHTTPChannel1.TargetURL := Edit1.Text;
with CoSmartService.Create(ROSOAPMessage1, ROWinInetHTTPChannel1) do
ShowMessage(DateTimeToStr(GetServerTime));
end ;
现在运行客户端应用程序
.
输入你的
Web
服务地址并点击
Add
和
GetTime
按钮
.
现在为我们的
Web
服务创建了功能完善的客户端
.
将你的
Web
服务升级到
Smart Service™
我们的服务运行良好
,
但是
RemObjects
同时提供给我们一些组件可以升级我们的
Web
服务
,
不但能支持
SOAP,
同时还可以支持高效的二进制流消息协议
.
二进制流协议支持加密和压缩
,
速度与标准的
SOAP
相比提示
80%. Smart Service
可以很容易的同时支持
SOAP
和二进制消息协议
. Let's see how!
在项目管理器中激活
SmartProject
服务项目
.
在
WebModule
中加入
TROBinMessage
并重命名
,
如图
:
点击
ROServer
控件的
Dispatchers
属性
.
弹出一个显示当前
ROServer
组件的所有消息分配器
.
你已经能看到对应的
SOAPMessage
控件的记录
.
在
"Path Info"
中指定
RO
消息对于的
URL
目录
.
当我们使用
http://localhost/isapi/SmartProject.dll/SOAP (
或相似的
)
调用我们的
Web
服务时
,
就暗示我们
RO
服务使用
ROSOAPMessage
对象解析消息
.
点击
Add
按钮在消息
ComboBox
中选择
BinMessage
组件
.
对话框将自动的在
Path Info
中添加
"BIN",
也可以编辑它
.
重新编译
SmartProject
服务
.
现在你的服务是
Smart Service™,
客户端可以使用
SOAP+HTTP
或
BIN+HTTP
来调用服务了
.
使用
Smart Service™
在
Delphi
项目管理器中激活客户端项目
,
找到主窗体
,
从中移出
SOAP Message
控件
.
点击
"File|New|Unit",
并保存为
ROFuncs.pas,
添加如下代码
.
注意这里我们根据
Locaton
参数生成
RO
消息对象
(SOAP
或
BIN):
unit ROFuncs;
interface
uses uROClient, uROProxy;
function GetMessage(Location: string ): TROMessage;
implementation
uses SysUtils, uROBINMessage, uROSOAPMessage, Classes;
function GetMessage(Location: string ): TROMessage;
begin
if (Length(Location) >
3
) and
(UpperCase(Copy(Location, Length(Location) -
3
,
4
)) =
'/BIN'
) then
begin
Result := TROBINMessage.Create( nil );
TROBINMessage(Result).UseCompression := True;
end else
begin
Result := TROSOAPMessage.Create(TComponent( nil ));
end ;
end ;
end ;
在主窗体中点击
ALT+F11
键调出
"Use Unit"
对话框
.
引用
"ROFuncs"
单元
.
对按钮事件处理程序作如下修改
(
蓝字
):
procedure
TForm2.Button1Click(Sender: TObject);
var
ROMsg: TROMessage;
begin
ROWinInetHTTPChannel1.TargetURL := Edit1.Text;
ROMsg := GetMessage(Edit1.Text);
try
with CoSmartService.Create(
ROMsg
, ROWinInetHTTPChannel1) do
ShowMessage(IntToStr(Sum(1, 2)));
finally
ROMsg.Free;
end
;
end ;
procedure
TForm2.Button2Click(Sender: TObject);
var
ROMsg: TROMessage;
begin
ROWinInetHTTPChannel1.TargetURL := Edit1.Text;
ROMsg := GetMessage(Edit1.Text);
try
with CoSmartService.Create(
ROMsg
, ROWinInetHTTPChannel1) do
ShowMessage(DateTimeToStr(GetServerTime));
finally
ROMsg.Free;
end
;
end ;
编译并运行程序
.
现在可以使用服务
URL+"/ SOAP"
通过
SOAP
协议调用
Smart Service,
或服务
URL+"/BIN"
通过
BIN
消息调用
.
其它工作由
RO
自动完成
.
本地化
Smart Service™
当今有一个集中处理业务逻辑的服务是非常必要的
.
然而却无法避免使用本地应用程序
.
越来越多的人可以连接
Internet,
但很多客户端还需要本地连接
. RemObjects Smart Services
只需要很少的代码就可以满足这个需求
.
这样你可以使用几乎一样的代码在本地使用你的
ISAPI Smart Service,
从你的
Smart Service
的
DLL
文件调用标准
SOAP Web Service.
RemObjects
提供了同
ISAPI
服务一样方便的向导创建本地链接库
.
然而我们希望修改现存的
ISAPI
服务得到一个本地服务
,
我们需要在
SmartProject
中加几行代码
.
在
Delphi
的项目管理器中激活
SmartProject
服务
.
右击
"SmartProject.dll"
项目节点
,
点击
"View Source"
菜单项
.
向项目
Uses
字句中引入
uRODLLServer, uROBINMessage
和
Windows
单元
.
增加如下代码
(
蓝色
):
var
BINMessage : TROBINMessage;
procedure
ROProc(Reason:integer);
begin
case
Reason of
DLL_PROCESS_ATTACH: begin
BINMessage := TROBINMessage.Create( NIL );
RegisterMessage(BINMessage);
end
;
DLL_PROCESS_DETACH: begin
BINMessage.Free;
end
;
end
;
end
;
exports
GetExtensionVersion,
HttpExtensionProc,
TerminateExtension;
begin
DLLProc:=@ROProc;
ROProc(DLL_PROCESS_ATTACH);
CoInitFlags := COINIT_MULTITHREADED;
Application.Initialize;
Application.CreateForm(TMainModule, MainModule);
Application.Run;
end .
重新编译服务
.
现在服务已经可以通过
HTTP
远程调用或同
DLL
一样本地调用
.
现在扩展我们的客户端测试一下
!
本地调用
Smart Service™
库
在
Delphi
的项目管理器中激活客户端项目
.
打开
RUFuncs.pas
文件
.
在
User
字句中增加
uROWinInetHTTPChannel
和
uRODLLChannel
的引用
.
增加
GetChannel()
方法
,
修改
GetMessage()
方法
(
蓝色字体
):
function
GetChannel(Location: string ): TROTransportChannel;
function
GetMessage(Location: string ): TROMessage;
implementation
uses
uROWinInetHTTPChannel, uRODLLChannel,
SysUtils, uROBINMessage, uROSOAPMessage, Classes ;
function
GetChannel(Location: string ): TROTransportChannel;
begin
if (FileExists(Location)) and (UpperCase(ExtractFileExt(Location)) = '.DLL') then
begin
Result := TRODLLChannel.Create( nil );
TRODLLChannel(Result).DLLName := Location;
end else
begin
Result := TROWinInetHTTPChannel.Create( nil );
TROWinInetHTTPChannel(Result).TargetURL := Location;
end ;
end ;
function
GetMessage(Location: string ): TROMessage;
begin
if
(FileExists(Location)) and (UpperCase(ExtractFileExt(Location)) = '.DLL') then
begin
Result := TROBINMessage.Create( nil );
TROBINMessage(Result).UseCompression := True;
end else
begin
if (Length(Location) > 3) and
(UpperCase(Copy(Location, Length(Location) - 3, 4)) = '/BIN') then
begin
Result := TROBINMessage.Create( nil );
TROBINMessage(Result).UseCompression := True;
end else
begin
Result := TROSOAPMessage.Create(TComponent( nil ));
end;
end;
end;
现在我们通过
Location
参数获取不同
RO
通道对象
,
并修改
GetMessage()
方法检查是否使用本地库文件
.
激活主窗体删除
WinInet
通道控件
.
修改按钮事件
(
蓝色字体
):
procedure
TForm2.Button1Click(Sender: TObject);
var
ROMsg: TROMessage;
ROChannel: TROTransportChannel;
begin
ROMsg := GetMessage(Edit1.Text);
ROChannel := GetChannel(Edit1.Text);
try
with CoSmartService.Create(ROMsg,
ROChannel
) do
ShowMessage(IntToStr(Sum(1, 2)));
finally
ROMsg.Free;
ROChannel.Free;
end;
end;
procedure
TForm2.Button2Click(Sender: TObject);
var
ROMsg: TROMessage;
ROChannel: TROTransportChannel;
begin
ROMsg := GetMessage(Edit1.Text);
ROChannel := GetChannel(Edit1.Text);
try
with CoSmartService.Create(ROMsg,
ROChannel
) do
ShowMessage(DateTimeToStr(GetServerTime));
finally
ROMsg.Free;
ROChannel.Free;
end;
end;
我们简单修改了按钮事件处理程序调用
GetChannel
方法根据服务地址得到恰当的通道对象
.
运行程序测试一下
!
在
Microsoft C#
中调用
Smart Service™
打开
Visual Studio IDE
后
,
点击
"File|New|Blank Solution".
选择
"Visual C# Projects"
目录中的
"ASP. NET Web Application"
项
.
如下填写对话框
:
点击
OK
按钮
.
按下图设计窗体
,
体格
TextBox,
两个
Button
和一个
Lable.
在
"Solution Explorer"
右击
"References"
目录点击
"Add Web Reference".
输入你的
Smart Service
的
SOAP URL
点击
GO
按钮
.
点击
"Add Reference"
按钮
.
给两个按钮添加处理事件
:
private
void Button1_Click( object sender, System.EventArgs e)
{
localhost.SmartServiceService SmartSrvc;
SmartSrvc = new localhost.SmartServiceService();
ResultLabel.Text = "1 + 2 = " + SmartSrvc.Sum(1, 2).ToString();
}
private
void Button2_Click( object sender, System.EventArgs e)
{
localhost.SmartServiceService SmartSrvc;
DateTime ServTime ;
SmartSrvc = new localhost.SmartServiceService();
ServTime = SmartSrvc.GetServerTime();
ResultLabel.Text = ServTime.ToString();
}
注意导入的
WSDL
信息可以使
Visual Studio. NET IDE
具有代码提示功能
:
现在点击
VS.NET IDE
的
"Run"
按钮测试
.
简单扩展
可见
RemObjects SDK
可以在任意地方为你的业务对象提供服务
,
本地或标准的
Web Service,
高效的
Smart Serivce™,
所有只需要几行代码
.
创建真正的可扩展程序已经前所未有的简单了
.