当前位置 : 主页 > 网页制作 > Nodejs >

使用RTC调用WebService

来源:互联网 收集:自由互联 发布时间:2021-06-24
使用RTC调用WebService WebService的协议 WebService协议,就目前来说基本上是一个已经趋于过时的东西了,目前最主流的微服务端SDK都基本上采用了Restful的方式来作为交互模型,其最主要的原

使用RTC调用WebService

WebService的协议

WebService协议,就目前来说基本上是一个已经趋于过时的东西了,目前最主流的微服务端SDK都基本上采用了Restful的方式来作为交互模型,其最主要的原因是应该是WebService传递数据的冗余性比较高。虽然已经趋于过时了,但是不少的服务还是采用了WebService来作为API的服务提供者,就拿我们公司来说,本来我是让Web组的别用WebService作为服务API来提供服务的,但是Web组的说,WebService他写起来最简单,特么的C#中直接[WebMethod]标记一下就作为WebService服务了,编写起来确实很方便,所以估计我想很多人估计也是类似的想法了。  
   说了这么多,其实都是废话哈哈,继续回到其协议上来说,WebService使用的是SOAP协议,soap协议只是用来封装消息用的。封装后的消息你可以通过各种已有的协议来传输,比如http,tcp/ip,smtp,等等,你甚至还一次用自定义的协议,当然也可以用https协议。那么WebService自然就是Http版本的SOAP传递数据了,说白了就是使用Http提交Xml格式数据,没啥太多的玄机在里面,知道了WebService就是Http提交XML数据之后,我们可做的事情就很简单了,那么就是模拟Http提交Xml数据就完事了呗,这个提交比较简单,麻烦的就是对于这个提交的Xml数据的构造上,这个就可以去看SOAP的协议格式文档了。其协议格式,记得是有有2个版本,一个SOAPV1,还有一个V2,两个的投递方式有一点区别,具体是啥的,好像是SOAPV1 Http投递的时候,HttpHeader中需要带上SOAPAction这个参数还是啥的,忘了,这个可以查看相关的协议文档。其投递的格式基本上类似如下:
<SOAP-ENV:Envelope  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Body>
       <m:WebServiceFuncName xmlns:m="Some-URI">
           <symbol>DIS</symbol>
       </m:WebServiceFuncName>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

也有类似这种的

<?xml version="1.0" encoding="utf-8"?>
   <SOAP-ENV:Envelope xmlns:ns0="http://webservice.hisinterface.hzyl.aspirecn.com/" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <ns1:Body>
   <ns0:ObjectParam>
      <arg0>%s</arg0>
      <arg1>%s</arg1>
   </ns0:ObjectParam>
   </ns1:Body>
   </SOAP-ENV>

调用WebService

WebService在Delphi中,其实Delphi是提供了调用WebService的方法的,这种Delphi自带的调用模式,我就不讲了,用起来比较简单,不过有一点很蛋疼,就是对于某些WebService,使用Delphi自带的方式自动创建的调用模式会各种调用失败,记得一直到XE7的版本都不行,更高的版本就不知道行不行了,一直使用RTC来模拟提交Http的一些相关请求,于是想到用WebService来做处理,根据前面的分析,已经很清楚了,只要构建好要投递的WebService的Xml内容,那么模拟提交就很简单了,至于这个模拟投递的内容如何处理,可以根据SOAP的协议格式来做处理,一般是
<m:WebServiceFuncName xmlns:m="WebServiceNameSpace">
  <Param1>参数1</Param1>
  <Param2>参数2</Param2>  
</m:WebServiceFuncName>

这种方式,也有传递对象的方式的,就是前面说的那种方式,总之根据协议格式去构建出Xml数据就能提交了。提交试用RtcDataRequest和RtcHttpClient
*delphi

const
  poststr = '<?xml version="1.0" encoding="utf-8"?>'#13#10+
   '<SOAP-ENV:Envelope xmlns:ns0="http://webservice.hisinterface.hzyl.aspirecn.com/" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">'#13#10+
   '<ns1:Body>'#13#10+
   '<ns0:request>'#13#10+
   ' <arg0>%s</arg0>'#13#10+
   ' <arg1>%s</arg1>'#13#10+
   '</ns0:request>'#13#10+
   '</ns1:Body>'#13#10+
   '</SOAP-ENV>';

procedure TForm1.Button1Click(Sender: TObject);
var
  Head,Body: string;
begin
  Body := '<body><oldPasswd>123456</oldPasswd><newPasswd>23423</newPasswd></body>';
  Head := '<head><operCode>S02</operCode><rsa>Edsuyufjewur038jfkfur74kfr449</rsa></head>';

  Head := stringReplace(Head,'<','&lt;',[rfReplaceAll]);
  Head := stringReplace(Head,'>','&gt;',[rfReplaceAll]);
  Body := stringReplace(Body,'<','&lt;',[rfReplaceAll]);
  Body := stringReplace(Body,'>','&gt;',[rfReplaceAll]);

  RtcDataRequest1.Tag := 0;
  RtcDataRequest1.Request.Method:='POST'; 
  RtcDataRequest1.Request.FileName:= '/hisinterface/service/request';
  RtcDataRequest1.Request.Host:=RtcHttpClient1.ServerAddr;
  RtcDataRequest1.Request.ContentType := 'application/soap+xml; charset=utf-8';
  RtcDataRequest1.Request.HeaderText:=RtcDataRequest1.Request.HeaderText+#13#10+'SOAPAction=http://218.201.202.252/hisinterface/service/request';
  self.RtcDataRequest1.Request.Params.Text := Format(poststr,[Head,Body]);
  self.RtcDataRequest1.Post();
  if self.RtcDataRequest1.WaitForCompletion() then
  begin
    Head := RtcDataRequest1.Client.Read;
    xmldocument1.LoadFromXML(Head);
    Memo1.Lines.Text := xmldocument1.ChildNodes[0].ChildNodes[0].ChildNodes[0].ChildNodes[0].Text;
  end;
end;

procedure TForm1.RtcDataRequest1BeginRequest(Sender: TRtcConnection);
var
  Cli:TRtcDataClient absolute Sender;
begin
  Cli.Write(Cli.Request.Params.Text);
end;

以上的代码是测试调用某公司的医保信息服务器的代码
那么,我们可以写一个比较通用的调用WebService的函数,完整代码如下,直接使用里面的
CallWebService则可用Rtc调用WebService

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, rtcConn, rtcDataCli,
  rtcHttpCli, rtcInfo,System.Generics.Collections;

type
  TForm1 = class(TForm)
    RtcDataRequest1: TRtcDataRequest;
    RtcHttpClient1: TRtcHttpClient;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure DoBeginRequest(Sender: TRtcConnection);
    procedure DoDataSent(Sender: TRtcConnection);
    procedure CallWebService(Url: string;MethodName: string;Params: TDictionary<string, string>;WebServiceNameSpace: string);
  end;

var
  Form1: TForm1;

implementation
uses QString,Qxml;
const MAX_SEND_Block_Size = 1460*44;
{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  params: TDictionary<string, string>;
begin
  params := TDictionary<string, string>.Create();
  params.AddOrSetValue('byProvinceName','北京');
  CallWebService('http://www.webxml.com.cn/WebServices/WeatherWebService.asmx','getSupportCity',params,'http://WebXml.com.cn/');
  params.Free;
end;

procedure TForm1.CallWebService(Url, MethodName: string; Params: TDictionary<string, string>; WebServiceNameSpace: string);
  function CreateWebServicePost: string;//构建WebService的提交数据
  var
    pair: TPair<string, string>;
    st: string;
  begin
    if WebServiceNameSpace = '' then
      WebServiceNameSpace := 'http://tempuri.org/';
    Result := '<?xml version="1.0" encoding="utf-8"?>'#13#10+
       '<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">'#13#10+
       ' <soap12:Body>'#13#10+
       ' <'+MethodName+' xmlns="'+WebServiceNameSpace+'">'#13#10;
    for pair in Params do
    begin
      st := pair.Key;
      if CompareText('SUBMIT',st) <> 0 then
        Result := Result + ' <'+st+'>'+rtcInfo.Utf8Encode(pair.Value)+ '</'+st+'>'#13#10
    end;
    result := result +
       ' </'+MethodName+'>'#13#10+
       ' </soap12:Body>'#13#10+
       '</soap12:Envelope>';
  end;
var
  st,srv,port: string;
  xml,rNode: TQxmlNode;
begin
  st := LowerCase(Url);
  if Pos('http://',st) <> 0 then
    st := Copy(st,8,MaxInt);
  srv := qstring.DecodeTokenW(st,'/','''',true,true);
  Url := st;
  st := qstring.DecodeTokenW(srv,':','''',true,true);
  if srv <> '' then
  begin
    port := srv;
  end
  else
  begin
    port := '';
  end;
  srv := st;
  url := '/'+url;
  RtcHttpClient1.ServerAddr := srv;
  if port = '' then
    RtcHttpClient1.ServerPort := '80'
  else RtcHttpClient1.ServerPort := port;
  RtcHttpClient1.AutoConnect := true;
  RtcHttpClient1.MultiThreaded := true;
  RtcHttpClient1.ReconnectOn.ConnectLost := true;
  RtcDataRequest1.Client := RtcHttpClient1;
  RtcDataRequest1.Request.Host := srv;
  RtcDataRequest1.OnBeginRequest := DoBeginRequest;
  RtcDataRequest1.OnDataSent := DoDataSent;
  RtcDataRequest1.Request.Params.Clear;
    //Request.Request.ItemName['SOAPAction'] := ''; //SOAP1.1,需要指定这个
  RtcDataRequest1.Request.FileName := url;
  RtcDataRequest1.Request.Params.Text := CreateWebServicePost;
  RtcDataRequest1.Request.ContentType := 'application/soap+xml; charset=utf-8';
  RtcDataRequest1.Request.Method := 'POST';
  RtcDataRequest1.Post; //提交内容
  if RtcDataRequest1.WaitForCompletion(False,30000) then //等待返回
  begin
    st := rtcInfo.Utf8Decode(RtcDataRequest1.Client.read);
    xml := TQXMLNode.Create;
    try
      xml.Parse(st);
      rNode := xml.ItemByPath('soap12:Envelope.soap12:Body.'+MethodName+'Response.'+MethodName+'.Result');
      if rNode <> nil then
        st := rNode.Text
      else st := xml.Text;
    except
      on e: exception do
      begin
        st := st + '无效地XML返回';
      end;
    end;
    xml.Free;
    ShowMessage(st);
  end;
end;

procedure TForm1.DoBeginRequest(Sender: TRtcConnection);
var
  st: RtcString;
  ilen: integer;
begin
  with TRtcDataClient(Sender) do
  begin
    if Request.Method = 'POST' then
    begin
      st := Request.Params.Text;
      ilen := Length(st);
      Request.ContentLength := ilen;
      if ilen <= MAX_SEND_Block_Size  then
        Write(st)
      else
      begin
        Write(Copy(st,1,MAX_SEND_Block_Size));
        st := Copy(st,1+MAX_SEND_Block_Size,MaxInt);
        Request.Info['WillSend'] := st; //将要发送的
      end;
    end
    else
      WriteHeader();
  end;
end;

procedure TForm1.DoDataSent(Sender: TRtcConnection);
var
  ilen: integer;
  st: RtcString;
begin
  with TRtcDataClient(Sender) do
  begin
    if Request.ContentLength>Request.ContentOut then
    begin
      ilen := Request.ContentLength-Request.ContentOut;
      st := Request.Info['WillSend'];
      if ilen <= MAX_SEND_Block_Size  then
        Write(st)
      else
      begin
        Request.Info['WillSend'] := Copy(st,1+MAX_SEND_Block_Size,MaxInt);
        Write(Copy(st,1,MAX_SEND_Block_Size));
      end;
    end;
  end;
end;

end.
网友评论