曾孝 發表於 2020-2-11 10:08:00

delphi Restful:客户端实现的四种方式及其比较

<h1>delphi Restful:客户端实现的四种方式</h1>
<h3><span style="color: rgba(229, 121, 182, 1)">摘要:转载自https://blog.csdn.net/pulledup/article/details/104132753</span></h3>
<p><br><strong>一、NetHTTP技术体系:&nbsp;</strong> TNetHTTPClient;&nbsp;&nbsp; TNetHTTPRequest<br><strong>二、REST技术体系:</strong><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TRESTClient; TRESTRequest; TRESTResponse; TRESTResponseDataSetAdapter<br><strong>三、Indy技术体系:</strong>IdHTTP + IdSSLOpenSSL&nbsp;<br><strong>四、浏览器客户端技术体系:</strong>JavaScript+jQuery(Mobile)+Http DOM+Ajax</p>
<p>&nbsp;</p>
<p style="text-align: center"><img alt="" class="has lazyload" data-src="https://img-blog.csdnimg.cn/20200201133440301.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p>&nbsp;</p>
<h3><span style="color: rgba(51, 153, 234, 1)"><strong>一、NetHTTP技术体系:</strong></span></h3>
<h3><span style="color: rgba(51, 153, 234, 1)"><strong>System.Net.HttpClient;&nbsp;&nbsp;System.Net.URLClient;&nbsp;&nbsp;System.Net.FileClient;&nbsp;</strong></span></h3>
<h3><span style="color: rgba(51, 153, 234, 1)"><strong>System.Net.Mime;&nbsp;&nbsp;System.Net.Socket;&nbsp;&nbsp;System.Net.HttpClientComponent;&nbsp;&nbsp;</strong></span></h3>
<h3><span style="color: rgba(243, 59, 69, 1)">非常强大!</span></h3>
<h3><span style="color: rgba(243, 59, 69, 1)">优势:</span></h3>
<p><strong>&nbsp; &nbsp; DX原生的:仅取决于操作系统,操作系统升级后,部署及其代码不会受到任何影响;不受组件的版本影响;可方便地Rest</strong></p>
<p><strong>&nbsp; &nbsp; 既能很好的支持TSession会话方式的基本鉴权,又能很好的支持<span style="color: rgba(229, 121, 182, 1)">AccessToken访问令牌</span>方式或代码方式的高级鉴权,有专门的非可视化鉴权类(TCertificateList = class(TList&lt;TCertificate&gt;);)支持,需要自己写代码去实现</strong></p>
<p><strong>&nbsp; &nbsp; </strong><strong>异常处理:</strong>强大、方便。</p>
<p><strong>属系统运行时刻库</strong></p>
<p>C:\Program Files (x86)\Embarcadero\Studio\20.0\source\rtl\net&nbsp;</p>
<p><strong>对应的原生组件:</strong>&nbsp; &nbsp;</p>
<p>&nbsp; &nbsp; NetHTTPClient1: TNetHTTPClient;<br>
&nbsp; &nbsp; NetHTTPRequest1: TNetHTTPRequest;</p>
<p style="text-align: center"><img alt="" class="has lazyload" height="445" width="500" data-src="https://img-blog.csdnimg.cn/20200201132638219.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p>既可直接使用组件</p>
<p>NetHTTPClient1: TNetHTTPClient;&nbsp;&nbsp;&nbsp; &nbsp; NetHTTPRequest1: TNetHTTPRequest;</p>
<p>也可以不使用组件,而动态产生</p>
<p><strong>官方案例1:</strong><span style="color: rgba(229, 121, 182, 1)">同步多线程文件分段下载:&nbsp;&nbsp;</span></p>
<p>&nbsp; &nbsp; D:\开发测试\Samples\Object Pascal\RTL\HttpDownload\HttpDownloadDemo.dproj</p>
<p>&nbsp; &nbsp; C:\Users\Public\Documents\Embarcadero\Studio\20.0\Samples\Object Pascal\RTL\HttpDownload</p>
<p style="text-align: center"><img alt="" class="has lazyload" data-src="https://img-blog.csdnimg.cn/20200210204234214.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p><strong>官方案例2:</strong><span style="color: rgba(229, 121, 182, 1)">异步单线程文件下载:&nbsp;&nbsp;</span></p>
<p>&nbsp; &nbsp; D:\开发测试\Samples\Object Pascal\RTL\HttpAsyncDownload\HttpAsyncDownloadDemo.dproj</p>
<p>&nbsp; &nbsp; C:\Users\Public\Documents\Embarcadero\Studio\20.0\Samples\Object Pascal\RTL\HttpAsyncDownload</p>
<p style="text-align: center"><img alt="" class="has lazyload" data-src="https://img-blog.csdnimg.cn/20200210204420915.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p><strong>第三方案例3:</strong><span style="color: rgba(229, 121, 182, 1)">HTTPClient的Rest方法获取Json数据&amp;并行库未来&amp;异步任务</span></p>
<p>&nbsp; &nbsp; D:\开发测试\Samples\其它\myTestCode\DelphiCookbookThirdEdition\Chapter05\CODE\RECIPE07\</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp; &nbsp; var<br>
&nbsp; &nbsp; &nbsp; MainForm: TMainForm;</p>
<p>&nbsp; &nbsp; implementation</p>
<p>&nbsp; &nbsp; uses<br>
&nbsp; &nbsp; &nbsp; System.Net.HTTPClient, System.JSON<br>
&nbsp; &nbsp; &nbsp; , AsyncTask<br>
&nbsp; &nbsp; &nbsp; , Converters<br>
&nbsp; &nbsp; &nbsp; ;</p>
<p>&nbsp; &nbsp; {$R *.dfm}</p>
<p>&nbsp; &nbsp; <span style="color: rgba(51, 153, 234, 1)">const</span><br>
&nbsp; &nbsp; &nbsp; <span style="color: rgba(51, 153, 234, 1)">ACCESS_KEY</span> = '58297a8c75e21d218b1da2c610b6f62c';&nbsp;</p>
<p><span style="color: rgba(51, 153, 234, 1)">&nbsp; &nbsp; &nbsp; &nbsp; //:Token鉴权思路:初次给常数,下载令牌文件,再次登录验证令牌办法的合法性</span></p>
<p>&nbsp; &nbsp; procedure TMainForm.<strong>FormCreate</strong>(Sender: TObject);<br>
&nbsp; &nbsp; var ListPair:TStringList; ListObject:TStringList;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LStrRespContent:string;<br>
&nbsp; &nbsp; &nbsp; &nbsp; //:以上我加的<br>
&nbsp; &nbsp; <strong><span style="color: rgba(51, 153, 234, 1)">//泛型异步任务:Rest调用数据、UI加载结果处理异常</span>:</strong>FormCreate事前获取币种,保存到TStringList中:<br>
&nbsp; &nbsp; begin<br>
&nbsp; &nbsp; &nbsp;<span style="color: rgba(51, 153, 234, 1)"><strong> Async.Run</strong>&lt;TStringList&gt;</span>(<br>
&nbsp; &nbsp; &nbsp; &nbsp; <strong>function: TStringList&nbsp;&nbsp;</strong>&nbsp;<span style="color: rgba(229, 121, 182, 1)"> //:异步任务:匿名线程执行函数:</span><br>
&nbsp; &nbsp; &nbsp; &nbsp; var<br><span style="color: rgba(229, 121, 182, 1)"><strong>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LHTTP: THTTPClient;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LResp: IHTTPResponse;</strong></span><br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LJObj: TJSONObject;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LJRates: TJSONObject;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; I: Integer;<br>
&nbsp; &nbsp; &nbsp; &nbsp; begin<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LHTTP := THTTPClient.Create;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <strong>//:步骤1:THTTPClient实例化</strong><br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: rgba(229, 121, 182, 1)"><strong>LResp := LHTTP.Get</strong></span>(<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;'http://data.fixer.io/api/latest' //:baseURL:TURI的baseURL部分:包括Scheme(协议https://等)+Path(路径)+Port(端口)等<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;+'?' &nbsp;//:FQuery:TURI查询指令部分<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;+'access_key='+<span style="color: rgba(51, 153, 234, 1)">ACCESS_KEY</span> //:TURIParameters:TURI参数部分(TNameValuePair名称=数值的对,参数间用’&amp;’分割)<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:在本例:access_key该参数相当于Token鉴权方式<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<strong> //:步骤2:THTTPClient获取URL的默认头定义的响应接口IHTTPResponse</strong></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LStrRespContent:=<span style="color: rgba(229, 121, 182, 1)"><strong>LResp.ContentAsString(TEncoding.UTF8);</strong></span></p>
<p><strong>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:步骤3:响应接口IHTTPResponse以UTF8编码获取响应结果的内容字符串</strong></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LStrRespContent:=<span style="color: rgba(229, 121, 182, 1)"><strong>TConverters.JsonReformat(LStrRespContent,true);</strong></span><br><strong>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:步骤4:格式化获取到的响应结果的内容字符串为缩进的JSon格式化的字符串<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:(便于阅读和调试)</strong><br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: rgba(229, 121, 182, 1)"><strong>LJObj := TJSONObject.ParseJSONValue (LStrRespContent) as TJSONObject;</strong></span></p>
<p><strong>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:步骤5:解析:获取到的响应结果的JSon格式化的字符串:为JSON对象:</strong></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LJRates := LJObj.GetValue&lt;TJSONObject&gt;('rates');<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ListPair := TStringList.Create;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ListObject:=TStringList.Create;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:我加的<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Result := TStringList.Create;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for I := 0 to LJRates.Count - 1 do<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //ListPair.Add( LJRates.Pairs.JsonString.Value +' : '<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //+ LJRates.Pairs.JsonValue.ToString );<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ListObject.Add( LJRates.Pairs.JsonString.Value +'='<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + LJRates.Pairs.JsonValue.ToString );<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ListPair.AddPair(LJRates.Pairs.JsonString.Value,<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LJRates.Pairs.JsonValue.ToString,<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ListObject );</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:我加的<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Result.Add(LJRates.Pairs.JsonString.Value);<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Result.Sort;//:成功回调值TStringList索引排序<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; finally<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LJObj.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; finally<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LHTTP.Free;</p>
<p><strong>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:步骤7:释放THTTPClient实例</strong><br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>
&nbsp; &nbsp; &nbsp; &nbsp; end,<br>
&nbsp; &nbsp; &nbsp; &nbsp; <strong>procedure(const Strings: TStringList)</strong><br>
&nbsp; &nbsp; &nbsp; &nbsp; begin&nbsp;<span style="color: rgba(229, 121, 182, 1)"> //:异步任务:主线程加载数据:</span></p>
<p><strong>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:步骤6:UI加载解析后的数据:</strong><br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Memo3.Clear;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Memo3.Lines.BeginUpdate;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: rgba(229, 121, 182, 1)">Memo3.Lines.Add(LStrRespContent);</span><br><strong>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:加载经过格式化的响应内容字符串<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:HTTP客户端Rest请求的JSon对象值(各币种对欧元)</strong><br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Memo3.Lines.EndUpdate;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cbSymbol.Items.Assign(Strings);//:下拉框赋值<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Memo1.Lines.Clear; Memo1.Lines.BeginUpdate;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Memo1.Lines.Add( (ListPair.Objects as TStrings).Text );<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Memo1.Lines.Add( ListPair.Text );<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Memo1.Lines.Add( ListObject.Text );<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Memo1.Lines.EndUpdate;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:加载各币种对欧元的实时汇率:<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Memo2.Lines.Clear; Memo2.Lines.BeginUpdate;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Memo2.Lines.Add( LStrRespContent ); Memo2.Lines.EndUpdate;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//:我加的<br>
&nbsp; &nbsp; &nbsp; &nbsp; end,<br><strong>&nbsp; &nbsp; &nbsp; &nbsp; procedure(const ExceptParallel:Exception)</strong><br>
&nbsp; &nbsp; &nbsp; &nbsp; begin&nbsp;&nbsp;<span style="color: rgba(229, 121, 182, 1)">//:异步任务:异常处理:</span><br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ExceptParallel.Message.Trim&lt;&gt;'' then<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ShowMessage('请求出错了');<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>
&nbsp; &nbsp; &nbsp; &nbsp; end</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; );<br>
&nbsp; &nbsp; end;<br>
&nbsp;</p>
<h3><span style="color: rgba(51, 153, 234, 1)"><strong>二、REST技术体系:</strong></span></h3>
<h3><span style="color: rgba(51, 153, 234, 1)">&nbsp; &nbsp; &nbsp; &nbsp;<strong>REST.Client;&nbsp;&nbsp;REST.Response.Adapter;&nbsp; &nbsp;REST.HttpClient;&nbsp;</strong>REST.Types<strong>;</strong> </span></h3>
<h3><span style="color: rgba(51, 153, 234, 1)">&nbsp; &nbsp; &nbsp; &nbsp;REST.Json, REST.Json.Interceptors;&nbsp;&nbsp; REST.BindSource;&nbsp; REST.Utils;&nbsp;</span></h3>
<h3><span style="color: rgba(51, 153, 234, 1)">&nbsp; &nbsp; &nbsp; &nbsp;REST.Authenticator.Basic;&nbsp;&nbsp;&nbsp;REST.Authenticator.OAuth;</span></h3>
<h3><strong><span style="color: rgba(243, 59, 69, 1)">TRESTClient的底层是THTTPClient:</span> 继承关系如下-&gt;&nbsp;TRESTHTTP -&gt;&nbsp;REST.Client-&gt;&nbsp;THTTPClient.Create-&gt;&nbsp;&nbsp;THTTPClient&nbsp; &nbsp; -&gt;&nbsp;&nbsp;&nbsp;System.Net.HttpClient</strong></h3>
<p><strong>DX原生的:仅取决于操作系统,操作系统升级后,部署及其代码不会受到任何影响;不受组件的版本影响;可方便地Rest</strong></p>
<p><span style="color: rgba(229, 121, 182, 1)"><strong>//:这一组Rest客户端组件只对返回Json数据有效,对流和Xml均无效:</strong></span></p>
<h3><span style="color: rgba(243, 59, 69, 1)">强大,好用,简单!</span></h3>
<h3><span style="color: rgba(243, 59, 69, 1)">优势:</span></h3>
<p><strong>1、REST.Json, REST.Json.Interceptors :体系中这套与Json的交互,既可用于客户端,也可用于服务器端</strong></p>
<p><strong>2、既能很好的支持TSession会话方式的基本鉴权,又能很好的支持<span style="color: rgba(229, 121, 182, 1)">AccessToken访问令牌</span>方式或代码方式的高级鉴权,有专门的非可视化鉴权单元(REST.Authenticator.Basic和REST.Authenticator.OAuth)支持,需要自己写代码去实现</strong></p>
<h3><span style="color: rgba(243, 59, 69, 1)">弱势:</span></h3>
<p><strong>如果网络异常或服务器程序未启动或服务器程序错误,异常,在处理异常方面麻烦一些,其异常类(ERequestError&nbsp; :uses Rest.Types)功能比较简单!</strong></p>
<p>C:\Program Files (x86)\Embarcadero\Studio\20.0\source\data\rest</p>
<p>&nbsp; &nbsp; RESTClient1: TRESTClient;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //uses&nbsp;REST.Client;<br>
&nbsp; &nbsp; RESTRequest1: TRESTRequest;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//uses&nbsp;REST.Client;<br>
&nbsp; &nbsp; RESTResponse1: TRESTResponse;&nbsp; &nbsp; &nbsp;//uses&nbsp;REST.Client;&nbsp;<br>
&nbsp; &nbsp; RESTResponseDataSetAdapter1: TRESTResponseDataSetAdapter;&nbsp; /uses&nbsp;REST.Response.Adapter;</p>
<p>&nbsp; &nbsp; REST.BindSource&nbsp; //:Rest客户端数据绑定源<br>
&nbsp; &nbsp; REST.Utils&nbsp; //:Rest客户端实用工具:<br>
&nbsp; &nbsp; &nbsp; &nbsp; //:URIEncode、ExtractURLSegmentNames、ExtractGetParams、<br>
&nbsp; &nbsp; &nbsp; &nbsp; //:RESTComponentIsDesigning、TRESTFindDefaultComponent&nbsp;<br>
&nbsp; &nbsp; REST.Authenticator.Basic&nbsp; &nbsp; //:Rest客户端基本鉴权单元:TSession会话方式<br>
&nbsp; &nbsp; REST.Authenticator.OAuth&nbsp; &nbsp;//:Rest客户端高级鉴权单元:AccessToken访问令牌方式或代码方式</p>
<p style="text-align: center"><img alt="" class="has lazyload" height="494" width="500" data-src="https://img-blog.csdnimg.cn/20200201134438118.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p style="text-align: center"><img alt="" class="has lazyload" height="488" width="500" data-src="https://img-blog.csdnimg.cn/20200201134529974.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p><span style="color: rgba(243, 59, 69, 1)"><strong>Rest体系的客户端架构方案:</strong></span></p>
<p><strong>uses</strong></p>
<p>&nbsp; ClientModuleUnit1, <strong>//:我的</strong>客户端数据模块<br>
&nbsp; <strong>Converters</strong><br>
&nbsp; &nbsp; //:我的Json到Bson的互转类、TBytes到String的互转类、JSon重新格式化、JSon到delphi代码转化、JSon到TJsonWriter代码转化、JSon到TJsonBuilder代码转化<br>
&nbsp; &nbsp; //:Converters:搜索路径:D:\PulledupO2O\myPublic\RTL\RTLSamples\Json</p>
<p>&nbsp; , <strong>AsyncTask</strong> //: 我的异步任务单元</p>
<p><strong>&nbsp; &nbsp; //以下为系统类别:</strong><br>
&nbsp; , System.Types,System.Variants,System.Classes<br>
&nbsp; , System.UITypes<br>
&nbsp; , System.SysUtils,System.IOUtils,System.StartUpCopy<br>
&nbsp; , System.Threading, System.SyncObjs //线程、任务;事件总线<br>
&nbsp; , System.<strong>Rtti</strong>//:系统运行时刻库(运行时的类型信息Run Time date Type Infomation):<br>
&nbsp; , System.<strong>NetEncoding</strong> &nbsp;//:系统网络编码的运行时刻库:编码加密、解码解密<br>
&nbsp; , System.Math //:系统数学函数库<br>
&nbsp; , system.hash //:系统自带的的Hash哈希单元<br>
&nbsp; , System.Devices //:系统设备描述单元<br>
&nbsp;<strong> //系统原生JSON类:</strong><br>
&nbsp; , System.JSON.Types<br>
&nbsp; , System.JSONConsts<br>
&nbsp; , System.JSON.Utils<br>
&nbsp; , System.JSON ,System.JSON.Readers<br>
&nbsp; , System.JSON.Builders<br>
&nbsp; //引用泛型对象*&lt;T&gt;的单元:<br>
&nbsp; //, System.TypInfo ,System.Generics.Collections ,System.Generics.Defaults</p>
<p>&nbsp;<strong> //Rest类:</strong><br>
&nbsp; , REST.Response.Adapter, REST.Client //:REST客户端组件引用: &nbsp;//组件TRESTClient TRESTRequest TRESTResponse TRESTResponseDataSetAdapter的单元:</p>
<p><span style="color: rgba(229, 121, 182, 1)">&nbsp; , REST.Types</span>//:Rest客户端请求的各种类型的常量、枚举的定义,异常捕获的定义<br><span style="color: rgba(229, 121, 182, 1)">&nbsp; , REST.Consts</span>//:Rest客户端的运行是提示常量<br><span style="color: rgba(243, 59, 69, 1)"><strong>&nbsp; //Rest的以下体系中这套与Json的交互,既可用于客户端,也可用于服务器端:</strong></span><br><span style="color: rgba(229, 121, 182, 1)">&nbsp; , REST.Json.Types</span> //:REST.Json特殊类型的运行时刻库:日期、布尔的编组与解析<br><span style="color: rgba(229, 121, 182, 1)">&nbsp; , REST.Json.Interceptors</span><br>
&nbsp; &nbsp; //:Json这些数据类型拦截器:实现对时区、日期时间中的分段、<br>
&nbsp; &nbsp; &nbsp; //:数组中的局部字符串:转TListOfObjects = array of TObject及其反转<br>
&nbsp; &nbsp; &nbsp; //:字符串中的局部字符串:转TObject及其反转<br><span style="color: rgba(229, 121, 182, 1)">&nbsp; , REST.Json</span><br>
&nbsp; &nbsp; //:TJson类封装:将TObject对象转Json和Json格式的string,<br>
&nbsp; &nbsp; &nbsp; //:Json和Json格式的string转对象TObject,<br>
&nbsp; &nbsp; &nbsp; //:Json格式化(TStringBuilder规范化重写)及<br>
&nbsp; &nbsp; &nbsp; //:Json和Json格式的string规范化UTF8编码<br><span style="color: rgba(229, 121, 182, 1)">&nbsp; , REST.JsonReflect</span><strong>//:Json映射:数据对象与编组、转化:</strong><br>
&nbsp; &nbsp; <strong>//:REST.JsonReflect来源于Data.DBXJSONReflect,只是它更轻量级.</strong><br>
&nbsp; &nbsp; //:最重要是它不依赖于注入到中JSON对象的元数据.<br>
&nbsp; &nbsp; //:它的目的是“reflect映射”Json属性到TObject,反之亦然.<br>
&nbsp; &nbsp; &nbsp; //:这里所有JSON对象创建或处理均以“plain”的方式对待.<br>
&nbsp; &nbsp; &nbsp; &nbsp; //在本单元实现方式从设计的观点来看仍然是“粗糙”的,<br>
&nbsp; &nbsp; &nbsp; &nbsp; //:但会随着时间的推移得以改善(10.3应该完善啦)<br>
&nbsp; &nbsp; //重要:这里严重涉及RTTI,因此可能不能被禁用,必须引用System.RTTI.<br>
&nbsp; &nbsp; //目前不建议直接使用这个单元,因为它的接口可能随时间而改变.<br>
&nbsp; &nbsp; &nbsp; //:推荐使用REST.Json中的TJson类(或Data.DBXJSONReflect).<br><span style="color: rgba(243, 59, 69, 1)">&nbsp; &nbsp; //REST.Json中的接口是稳定的.</span><br>
&nbsp; &nbsp; &nbsp; //:10.0以前暂不建议直接使用它(10.3应该完善啦)<br>
&nbsp; &nbsp; <span style="color: rgba(243, 59, 69, 1)"><strong>//:可替代方案:</strong></span>使用以下两个JSon映射互转的封装:<br>
&nbsp; <strong>//数据库的JSon映射:数据对象与编组、转化:</strong><br><span style="color: rgba(124, 121, 229, 1)">&nbsp; , Data.FireDACJSONReflect &nbsp;,Data.DBXJSONReflect</span><br>
&nbsp; , Data.DBXJSONCommon&nbsp; //:数据库DBX的通用JSON<br><strong>&nbsp; // 数据库:</strong>字段列表、字段、对象字段、数据链接、数据源、字段选项、字段定义列表、索引列表定义<strong>:</strong><br>
&nbsp; , Data.DB<br>
&nbsp; <strong>//Dbx数据压缩及过滤器:</strong><br>
&nbsp; , Data.DbxCompressionFilter<br>
&nbsp; <strong>//数据绑定单元:</strong><br>
&nbsp; , Data.Bind.Components ,Data.Bind.ObjectScope</p>
<p><strong>官方案例1:</strong></p>
<p><strong>&nbsp; &nbsp;&nbsp;</strong>D:\开发测试\Samples\Object Pascal\Database\RESTDemo</p>
<p>&nbsp; &nbsp;&nbsp;C:\Users\Public\Documents\Embarcadero\Studio\20.0\Samples\Object Pascal\Database\RESTDemo</p>
<p style="text-align: center"><img alt="" class="has lazyload" width="500" data-src="https://img-blog.csdnimg.cn/20200201181712765.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p>&nbsp;<strong>适配JSon数据到客户端数据集:</strong></p>
<p style="text-align: center"><img alt="" class="has lazyload" height="143" width="248" data-src="https://img-blog.csdnimg.cn/20200201181852538.png"></p>
<p><strong>官方案例2:</strong></p>
<p><strong>&nbsp; &nbsp;&nbsp;</strong>D:\开发测试\Samples\Object Pascal\DataSnap\FireDACJSONReflect\sysClass\source\data\rest\restdebugger\RESTDebugger.dproj</p>
<p><strong>&nbsp; &nbsp;&nbsp;</strong>C:\Program Files (x86)\Embarcadero\Studio\20.0\source\data\rest\restdebugger\RESTDebugger.dproj</p>
<p style="text-align: center"><img alt="" class="has lazyload" data-src="https://img-blog.csdnimg.cn/20200210000927894.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p style="text-align: center"><img alt="" class="has lazyload" data-src="https://img-blog.csdnimg.cn/20200210001055945.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p><strong>或者:</strong></p>
<p style="text-align: center"><img alt="" class="has lazyload" data-src="https://img-blog.csdnimg.cn/20200210001612501.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p><span style="color: rgba(51, 153, 234, 1)"><strong>2.1、 </strong></span></p>
<p>---&gt;<strong>默认值常量:</strong></p>
<p><span style="color: rgba(243, 59, 69, 1)">REST.Types;</span></p>
<p><strong>&nbsp; TCompletionHandler = TProc;<br>
&nbsp; TCompletionHandlerWithError = TProc&lt;TObject&gt;;</strong></p>
<p><strong>&nbsp; TRESTObjectOwnership = (ooCopy, ooREST, ooApp);</strong></p>
<p><strong>&nbsp; TRESTRequestParameterOption枚举</strong></p>
<p>&nbsp; TRESTRequestParameterOptions = set of TRESTRequestParameterOption;<br>
&nbsp; <strong>TRESTRequestParameterKind枚举</strong></p>
<p>&nbsp; &nbsp; pkGETorPOST<br>
&nbsp; &nbsp; pkURLSEGMENT<br>
&nbsp; &nbsp; pkREQUESTBODY<br>
&nbsp; &nbsp; pkQUERY</p>
<p>&nbsp; <strong>DefaultRESTRequestParameterKind</strong>: TRESTRequestParameterKind = TRESTRequestParameterKind.pkGETorPOST;<br>
&nbsp; function <strong>RESTRequestParameterKindToString</strong>(const AKind: TRESTRequestParameterKind): string;<br>
&nbsp; function <strong>RESTRequestParameterKindFromString</strong>(const AKindString: string): TRESTRequestParameterKind;</p>
<p><span style="color: rgba(51, 153, 234, 1)"><strong>2.2、 </strong></span></p>
<p>&nbsp; &nbsp; type<br>
&nbsp; &nbsp; &nbsp; /// &lt;summary&gt;<br>
&nbsp; &nbsp; &nbsp; /// Content<br>
&nbsp; &nbsp; &nbsp; /// &lt;/summary&gt;<br>
&nbsp; &nbsp; &nbsp; <strong>TRESTContentType</strong> = (ctNone, ctAPPLICATION_ATOM_XML, ctAPPLICATION_ECMASCRIPT, ctAPPLICATION_EDI_X12,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_EDIFACT, ctAPPLICATION_JSON, ctAPPLICATION_JAVASCRIPT, ctAPPLICATION_OCTET_STREAM, ctAPPLICATION_OGG,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_PDF, ctAPPLICATION_POSTSCRIPT, ctAPPLICATION_RDF_XML, ctAPPLICATION_RSS_XML, ctAPPLICATION_SOAP_XML,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_FONT_WOFF, ctAPPLICATION_XHTML_XML, ctAPPLICATION_XML, ctAPPLICATION_XML_DTD, ctAPPLICATION_XOP_XML,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_ZIP, ctAPPLICATION_GZIP, ctTEXT_CMD, ctTEXT_CSS, ctTEXT_CSV, ctTEXT_HTML, ctTEXT_JAVASCRIPT,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctTEXT_PLAIN, ctTEXT_VCARD, ctTEXT_XML, ctAUDIO_BASIC, ctAUDIO_L24, ctAUDIO_MP4, ctAUDIO_MPEG, ctAUDIO_OGG,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAUDIO_VORBIS, ctAUDIO_VND_RN_REALAUDIO, ctAUDIO_VND_WAVE, ctAUDIO_WEBM, ctIMAGE_GIF, ctIMAGE_JPEG, ctIMAGE_PJPEG,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctIMAGE_PNG, ctIMAGE_SVG_XML, ctIMAGE_TIFF, ctMESSAGE_HTTP, ctMESSAGE_IMDN_XML, ctMESSAGE_PARTIAL, ctMESSAGE_RFC822,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctMODEL_EXAMPLE, ctMODEL_IGES, ctMODEL_MESH, ctMODEL_VRML, ctMODEL_X3D_BINARY, ctMODEL_X3D_VRML, ctMODEL_X3D_XML,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctMULTIPART_MIXED, ctMULTIPART_ALTERNATIVE, ctMULTIPART_RELATED, ctMULTIPART_FORM_DATA, ctMULTIPART_SIGNED,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctMULTIPART_ENCRYPTED, ctVIDEO_MPEG, ctVIDEO_MP4, ctVIDEO_OGG, ctVIDEO_QUICKTIME, ctVIDEO_WEBM, ctVIDEO_X_MATROSKA,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctVIDEO_X_MS_WMV, ctVIDEO_X_FLV, ctAPPLICATION_VND_OASIS_OPENDOCUMENT_TEXT,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_VND_OASIS_OPENDOCUMENT_SPREADSHEET, ctAPPLICATION_VND_OASIS_OPENDOCUMENT_PRESENTATION,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_VND_OASIS_OPENDOCUMENT_GRAPHICS, ctAPPLICATION_VND_MS_EXCEL,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_SPREADSHEETML_SHEET, ctAPPLICATION_VND_MS_POWERPOINT,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_PRESENTATIONML_PRESENTATION,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_WORDPROCESSINGML_DOCUMENT, ctAPPLICATION_VND_MOZILLA_XUL_XML,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_VND_GOOGLE_EARTH_KML_XML, ctAPPLICATION_VND_GOOGLE_EARTH_KMZ, ctAPPLICATION_VND_DART,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_VND_ANDROID_PACKAGE_ARCHIVE, ctAPPLICATION_X_DEB, ctAPPLICATION_X_DVI, ctAPPLICATION_X_FONT_TTF,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_X_JAVASCRIPT, ctAPPLICATION_X_LATEX, ctAPPLICATION_X_MPEGURL, ctAPPLICATION_X_RAR_COMPRESSED,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_X_SHOCKWAVE_FLASH, ctAPPLICATION_X_STUFFIT, ctAPPLICATION_X_TAR, ctAPPLICATION_X_WWW_FORM_URLENCODED,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_X_XPINSTALL, ctAUDIO_X_AAC, ctAUDIO_X_CAF, ctIMAGE_X_XCF, ctTEXT_X_GWT_RPC, ctTEXT_X_JQUERY_TMPL,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctTEXT_X_MARKDOWN, ctAPPLICATION_X_PKCS12, ctAPPLICATION_X_PKCS7_CERTIFICATES, ctAPPLICATION_X_PKCS7_CERTREQRESP,<br>
&nbsp; &nbsp; &nbsp; &nbsp; ctAPPLICATION_X_PKCS7_MIME, ctAPPLICATION_X_PKCS7_SIGNATURE, ctAPPLICATION_VND_EMBARCADERO_FIREDAC_JSON);</p>
<p>&nbsp; &nbsp; <strong>var</strong><br>
&nbsp; &nbsp; &nbsp; <strong>DefaultRESTContentType: TRESTContentType = TRESTContentType.ctNone;</strong></p>
<p>&nbsp; &nbsp; <strong>const</strong><br>
&nbsp; &nbsp; &nbsp; /// &lt;summary&gt;<br>
&nbsp; &nbsp; &nbsp; /// <strong>HTTP <span style="color: rgba(243, 59, 69, 1)">Content-Type</span> (or <span style="color: rgba(243, 59, 69, 1)">MIME Types</span> as per RFC 2046) header Definitions.</strong><br>
&nbsp; &nbsp; &nbsp; /// &lt;/summary&gt;<br>
&nbsp; &nbsp; &nbsp; /// &lt;remarks&gt;<br>
&nbsp; &nbsp; &nbsp; /// &lt;para&gt;<br>
&nbsp; &nbsp; &nbsp; /// See: http://tools.ietf.org/html/rfc2046<br>
&nbsp; &nbsp; &nbsp; /// &lt;/para&gt;<br>
&nbsp; &nbsp; &nbsp; /// &lt;para&gt;<br>
&nbsp; &nbsp; &nbsp; /// Values collected from https://en.wikipedia.org/wiki/MIME_type<br>
&nbsp; &nbsp; &nbsp; /// &lt;/para&gt;<br>
&nbsp; &nbsp; &nbsp; /// &lt;/remarks&gt;</p>
<p>&nbsp; &nbsp; &nbsp; <strong>CONTENTTYPE</strong>_NONE = ''; // do not localize<br>
&nbsp; &nbsp; &nbsp; // Type Application<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_ATOM_XML = 'application/atom+xml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_ECMASCRIPT = 'application/ecmascript'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_EDI_X12 = 'application/EDI-X12'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_EDIFACT = 'application/EDIFACT'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_JSON = 'application/json'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_JAVASCRIPT = 'application/javascript'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_OCTET_STREAM = 'application/octet-stream'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_OGG = 'application/ogg'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_PDF = 'application/pdf'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_POSTSCRIPT = 'application/postscript'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_RDF_XML = 'application/rdf+xml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_RSS_XML = 'application/rss+xml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_SOAP_XML = 'application/soap+xml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_FONT_WOFF = 'application/font-woff'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_XHTML_XML = 'application/xhtml+xml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_XML = 'application/xml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_XML_DTD = 'application/xml-dtd'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_XOP_XML = 'application/xop+xml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_ZIP = 'application/zip'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_GZIP = 'application/gzip'; // do not localize<br>
&nbsp; &nbsp; &nbsp; // Type Text<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_TEXT_CMD = 'text/cmd'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_TEXT_CSS = 'text/css'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_TEXT_CSV = 'text/csv'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_TEXT_HTML = 'text/html'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_TEXT_JAVASCRIPT = 'text/javascript'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_TEXT_PLAIN = 'text/plain'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_TEXT_VCARD = 'text/vcard'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_TEXT_XML = 'text/xml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; // Type Audio<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_AUDIO_BASIC = 'audio/basic'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_AUDIO_L24 = 'audio/L24'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_AUDIO_MP4 = 'audio/mp4'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_AUDIO_MPEG = 'audio/mpeg'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_AUDIO_OGG = 'audio/ogg'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_AUDIO_VORBIS = 'audio/vorbis'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_AUDIO_VND_RN_REALAUDIO = 'audio/vnd.rn-realaudio'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_AUDIO_VND_WAVE = 'audio/vnd.wave'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_AUDIO_WEBM = 'audio/webm'; // do not localize<br>
&nbsp; &nbsp; &nbsp; // Type Image<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_IMAGE_GIF = 'image/gif'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_IMAGE_JPEG = 'image/jpeg'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_IMAGE_PJPEG = 'image/pjpeg'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_IMAGE_PNG = 'image/png'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_IMAGE_SVG_XML = 'image/svg+xml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_IMAGE_TIFF = 'image/tiff'; // do not localize<br>
&nbsp; &nbsp; &nbsp; // Type Message<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MESSAGE_HTTP = 'message/http'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MESSAGE_IMDN_XML = 'message/imdn+xml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MESSAGE_PARTIAL = 'message/partial'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MESSAGE_RFC822 = 'message/rfc822'; // do not localize<br>
&nbsp; &nbsp; &nbsp; // Type Model (3D Models)<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MODEL_EXAMPLE = 'model/example'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MODEL_IGES = 'model/iges'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MODEL_MESH = 'model/mesh'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MODEL_VRML = 'model/vrml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MODEL_X3D_BINARY = 'model/x3d+binary'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MODEL_X3D_VRML = 'model/x3d+vrml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MODEL_X3D_XML = 'model/x3d+xml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; // Type Multipart<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MULTIPART_MIXED = 'multipart/mixed'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MULTIPART_ALTERNATIVE = 'multipart/alternative'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MULTIPART_RELATED = 'multipart/related'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MULTIPART_FORM_DATA = 'multipart/form-data'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MULTIPART_SIGNED = 'multipart/signed'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_MULTIPART_ENCRYPTED = 'multipart/encrypted'; // do not localize<br>
&nbsp; &nbsp; &nbsp; // Type Video<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_VIDEO_MPEG = 'video/mpeg'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_VIDEO_MP4 = 'video/mp4'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_VIDEO_OGG = 'video/ogg'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_VIDEO_QUICKTIME = 'video/quicktime'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_VIDEO_WEBM = 'video/webm'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_VIDEO_X_MATROSKA = 'video/x-matroska'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_VIDEO_X_MS_WMV = 'video/x-ms-wmv'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_VIDEO_X_FLV = 'video/x-flv'; // do not localize<br>
&nbsp; &nbsp; &nbsp; // Type Application - Vendor Specific<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_OASIS_OPENDOCUMENT_TEXT = 'application/vnd.oasis.opendocument.text'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_OASIS_OPENDOCUMENT_SPREADSHEET = 'application/vnd.oasis.opendocument.spreadsheet';<br>
&nbsp; &nbsp; &nbsp; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_OASIS_OPENDOCUMENT_PRESENTATION = 'application/vnd.oasis.opendocument.presentation';<br>
&nbsp; &nbsp; &nbsp; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_OASIS_OPENDOCUMENT_GRAPHICS = 'application/vnd.oasis.opendocument.graphics';<br>
&nbsp; &nbsp; &nbsp; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_MS_EXCEL = 'application/vnd.ms-excel'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_SPREADSHEETML_SHEET =<br>
&nbsp; &nbsp; &nbsp; &nbsp; 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_MS_POWERPOINT = 'application/vnd.ms-powerpoint'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_PRESENTATIONML_PRESENTATION =<br>
&nbsp; &nbsp; &nbsp; &nbsp; 'application/vnd.openxmlformats-officedocument.presentationml.presentation'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_WORDPROCESSINGML_DOCUMENT =<br>
&nbsp; &nbsp; &nbsp; &nbsp; 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_MOZILLA_XUL_XML = 'application/vnd.mozilla.xul+xml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_GOOGLE_EARTH_KML_XML = 'application/vnd.google-earth.kml+xml'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_GOOGLE_EARTH_KMZ = 'application/vnd.google-earth.kmz'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_DART = 'application/vnd.dart'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_ANDROID_PACKAGE_ARCHIVE = 'application/vnd.android.package-archive'; // do not localize<br>
&nbsp; &nbsp; &nbsp; // Type X (RFC 6648)<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_DEB = 'application/x-deb'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_DVI = 'application/x-dvi'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_FONT_TTF = 'application/x-font-ttf'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_JAVASCRIPT = 'application/x-javascript'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_LATEX = 'application/x-latex'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_MPEGURL = 'application/x-mpegURL'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_RAR_COMPRESSED = 'application/x-rar-compressed'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_SHOCKWAVE_FLASH = 'application/x-shockwave-flash'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_STUFFIT = 'application/x-stuffit'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_TAR = 'application/x-tar'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_WWW_FORM_URLENCODED = 'application/x-www-form-urlencoded'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_XPINSTALL = 'application/x-xpinstall'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_AUDIO_X_AAC = 'audio/x-aac'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_AUDIO_X_CAF = 'audio/x-caf'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_IMAGE_X_XCF = 'image/x-xcf'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_TEXT_X_GWT_RPC = 'text/x-gwt-rpc'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_TEXT_X_JQUERY_TMPL = 'text/x-jquery-tmpl'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_TEXT_X_MARKDOWN = 'text/x-markdown'; // do not localize<br>
&nbsp; &nbsp; &nbsp; // Type PKCS (Cryptography)<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_PKCS12 = 'application/x-pkcs12'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_PKCS7_CERTIFICATES = 'application/x-pkcs7-certificates'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_PKCS7_CERTREQRESP = 'application/x-pkcs7-certreqresp'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_PKCS7_MIME = 'application/x-pkcs7-mime'; // do not localize<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_X_PKCS7_SIGNATURE = 'application/x-pkcs7-signature'; // do not localize<br>
&nbsp; &nbsp; &nbsp; // Type Application - Embarcadero Specific<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_APPLICATION_VND_EMBARCADERO_FIREDAC_JSON = 'application/vnd.embarcadero.firedac+json'; // do not localize</p>
<p>&nbsp; &nbsp; function <strong>ContentTypeToString</strong>(AContentType: TRESTContentType): string;<br>
&nbsp; &nbsp; function <strong>ContentTypeFromString</strong>(const AContentType: string): TRESTContentType;</p>
<p>&nbsp; &nbsp; function <strong>IsTextualContentType</strong>(AContentType: <strong>TRESTContentType</strong>) : boolean; overload;<br>
&nbsp; &nbsp; function <strong>IsTextualContentType</strong>(const AContentType: <strong>string</strong>) : boolean; overload;<br>
&nbsp;</p>
<p><span style="color: rgba(51, 153, 234, 1)"><strong>2.3、 </strong></span></p>
<p><strong>TRESTRequestMethod枚举</strong></p>
<p>&nbsp; rmPOST<br>
&nbsp; rmPUT<br>
&nbsp; rmGET<br>
&nbsp; rmDELETE<br>
&nbsp; rmPATCH</p>
<p>---&gt;</p>
<p>&nbsp; <strong>const</strong><br>
&nbsp; &nbsp; <strong>sRequestDefaultAccept</strong> = CONTENTTYPE_APPLICATION_JSON + ', ' +<br>
&nbsp; &nbsp; &nbsp; CONTENTTYPE_TEXT_PLAIN + '; q=0.9, ' + CONTENTTYPE_TEXT_HTML + ';q=0.8,';<br>
&nbsp; &nbsp; // UTF-8 is prefered, any other is good, but marked down:<br>
&nbsp; &nbsp; <strong>sRequestDefaultAcceptCharset</strong> = 'utf-8, *;q=0.8';<br>
&nbsp; &nbsp; <strong>sDefaultFallbackCharSetEncoding</strong> = 'utf-8';<br>
&nbsp; &nbsp; <strong>sDefaultUserAgent</strong> = 'Embarcadero RESTClient/' + RESTCLIENT_VERSION;<br>
&nbsp; &nbsp; <strong>sBody</strong> = 'body';<br>
&nbsp; &nbsp; <strong>sFile</strong> = 'file';</p>
<p><span style="color: rgba(51, 153, 234, 1)"><strong>2.4、 </strong></span></p>
<p><strong><span style="color: rgba(51, 153, 234, 1)">RESTRequest.ResetToDefaults;</span></strong></p>
<p>&nbsp; &nbsp; Method := <strong>DefaultRESTRequestMethod</strong>;<br>
&nbsp; &nbsp; Resource := '';<br>
&nbsp; &nbsp; ResourceSuffix := '';<br>
&nbsp; &nbsp; Timeout := 30000; // Some servers may be slow. Esp if they just recycled and need to start up on their first request<br>
&nbsp; &nbsp; Accept := sRequestDefaultAccept;<br>
&nbsp; &nbsp; AcceptCharset := sRequestDefaultAcceptCharset;<br>
&nbsp; &nbsp; HandleRedirects := True;<br>
&nbsp; &nbsp; FExecutionPerformance.Clear;<br>
&nbsp; &nbsp; FURLAlreadyEncoded := False;<br>
&nbsp; &nbsp; FParams.Clear;<br>
&nbsp; &nbsp; FTransientParams.Clear;<br>
&nbsp; &nbsp; FBody.ClearBody;<br>
&nbsp; &nbsp; if FClient &lt;&gt; nil then<br>
&nbsp; &nbsp; &nbsp; FClient.ContentType := '';<br>
&nbsp; &nbsp; if FResponse &lt;&gt; nil then<br>
&nbsp; &nbsp; &nbsp; FResponse.ResetToDefaults;<br>
&nbsp; &nbsp; // we intentionally do not reset "FAutoCreateParams"</p>
<p>&nbsp; var<br>
&nbsp; &nbsp; <strong>DefaultRESTRequestMethod</strong>: TRESTRequestMethod = <strong>TRESTRequestMethod.rmGET</strong>;</p>
<p>&nbsp; &nbsp; function <strong>RESTRequestMethodToString</strong>(const AMethod: <strong>TRESTRequestMethod</strong>): string;<br>
&nbsp;</p>
<p><strong>&nbsp;<span style="color: rgba(51, 153, 234, 1)"> RESTClient.ResetToDefaults;</span></strong></p>
<p>&nbsp; &nbsp; CreateHttpClient;<br>
&nbsp; &nbsp; BaseURL := '';<br>
&nbsp; &nbsp; ProxyServer := '';<br>
&nbsp; &nbsp; ProxyPort := 0;<br>
&nbsp; &nbsp; ProxyUsername := '';<br>
&nbsp; &nbsp; ProxyPassword := '';<br>
&nbsp; &nbsp; UserAgent := sDefaultUserAgent;<br>
&nbsp; &nbsp; FallbackCharsetEncoding := sDefaultFallbackCharSetEncoding;<br>
&nbsp; &nbsp; FSynchronizedEvents := True;<br>
&nbsp; &nbsp; FRaiseExceptionOn500 := True;<br>
&nbsp; &nbsp; FAutoCreateParams := True;<br>
&nbsp; &nbsp; FParams.Clear;<br>
&nbsp; &nbsp; FTransientParams.Clear;</p>
<p><br><span style="color: rgba(51, 153, 234, 1)">&nbsp;<strong> RESTResponse.ResetToDefaults;</strong></span></p>
<p>&nbsp;</p>
<p><br><span style="color: rgba(51, 153, 234, 1)">&nbsp; <strong>RESTResponseDataSetAdapter.ResetToDefaults;</strong></span></p>
<p>---&gt;</p>
<p>&nbsp;</p>
<p>&nbsp; <span style="color: rgba(229, 121, 182, 1)"><strong>TRESTResponse</strong></span> = class(TCustomRESTResponse)<br>
&nbsp; published<br>
&nbsp; &nbsp; property Content;<br>
&nbsp; &nbsp; property ContentLength;<br>
&nbsp; &nbsp; property ContentType;<br>
&nbsp; &nbsp; property ContentEncoding;<br>
&nbsp; &nbsp; property RootElement;<br>
&nbsp; &nbsp; property BindSource;<br>
&nbsp; end;</p>
<p><span style="color: rgba(51, 153, 234, 1)"><strong>2.5、 </strong></span>&nbsp; <span style="color: rgba(229, 121, 182, 1)"><strong>TRESTClient</strong></span> = class(TCustomRESTClient)<br>
&nbsp; published<br>
&nbsp; &nbsp; property Authenticator;<br>
&nbsp; &nbsp; property Accept;<br>
&nbsp; &nbsp; property AcceptCharset;<br>
&nbsp; &nbsp; property AcceptEncoding;<br>
&nbsp; &nbsp; property AllowCookies;<br>
&nbsp; &nbsp; property AutoCreateParams;<br>
&nbsp; &nbsp; property BaseURL;<br>
&nbsp; &nbsp; property ContentType;<br>
&nbsp; &nbsp; property FallbackCharsetEncoding;<br>
&nbsp; &nbsp; property Params;<br>
&nbsp; &nbsp; property HandleRedirects;<br>
&nbsp; &nbsp; property RedirectsWithGET;<br>
&nbsp; &nbsp; property SecureProtocols;<br>
&nbsp; &nbsp; property ProxyPassword;<br>
&nbsp; &nbsp; property ProxyPort;<br>
&nbsp; &nbsp; property ProxyServer;<br>
&nbsp; &nbsp; property ProxyUsername;<br>
&nbsp; &nbsp; property RaiseExceptionOn500;<br>
&nbsp; &nbsp; property SynchronizedEvents;<br>
&nbsp; &nbsp; property UserAgent;<br>
&nbsp; &nbsp; property OnHTTPProtocolError;<br>
&nbsp; &nbsp; property BindSource;<br>
&nbsp; &nbsp; property OnValidateCertificate;<br>
&nbsp; &nbsp; property OnNeedClientCertificate;<br>
&nbsp; &nbsp; property OnAuthEvent;<br>
&nbsp; end;</p>
<p><strong>&nbsp; &nbsp;</strong><span style="color: rgba(51, 153, 234, 1)"><strong>2.6、 </strong></span><strong>//以流的方式下载1个文件</strong>: Download a file</p>
<p>&nbsp; <span style="color: rgba(229, 121, 182, 1)"><strong>TDownloadURL</strong></span> = class<br>
&nbsp; private<br>
&nbsp; &nbsp; class procedure CheckForError(const AResponse: <strong>TCustomRESTResponse</strong>); static;<br>
&nbsp; public<br>
&nbsp; &nbsp; class procedure DownloadRawBytes(const AURL: string; const AStream: <strong>TStream</strong>); static;<br>
&nbsp; end;</p>
<p><span style="color: rgba(51, 153, 234, 1)"><strong>2.7、 </strong></span><span style="color: rgba(243, 59, 69, 1)"><strong>TRESTRequest在执行时,</strong></span><strong>如果网络异常或服务器程序未启动或服务器程序错误,异常,在<span style="color: rgba(243, 59, 69, 1)">处理异常方面</span>麻烦一些,其异常类(ERequestError&nbsp; :uses Rest.Types)功能比较简单!</strong></p>
<p><span style="color: rgba(51, 153, 234, 1)"><strong>2.8、 TRESTRequest同步执行模式:</strong></span></p>
<p><strong>provedure TCustomRESTRequest.<span style="color: rgba(243, 59, 69, 1)">Execute</span>;</strong></p>
<p><span style="color: rgba(51, 153, 234, 1)"><strong>2.9、 TRESTRequest异步执行模式:</strong></span></p>
<p>&nbsp;<strong> function TCustomRESTRequest.<span style="color: rgba(243, 59, 69, 1)">ExecuteAsync</span></strong>(<br>
&nbsp; &nbsp; ACompletionHandler: TCompletionHandler = nil;&nbsp;<br>
&nbsp; &nbsp; ASynchronized: boolean = True;<br>
&nbsp; &nbsp; AFreeThread: boolean = True;&nbsp;<br>
&nbsp; &nbsp; ACompletionHandlerWithError: TCompletionHandlerWithError = nil<br>
&nbsp; ): TRESTExecutionThread;<br><br>
&nbsp;Executes a request asynchronously, i.e. run it in its own thread. There is no automatic serialization op<br>
&nbsp;property access though, which means that while the execution thread runs, properties of all involved<br>
&nbsp;TCustomRESTClient and TCustomRESTRequest instances should not be touched from other threads (including the main thread)<br>
&nbsp;Using ExecuteAsync is strongly recommended on mobile platforms. iOS (and likely Android) will<br>
&nbsp;terminate an application if it considers the main thread to be unresponsive, which would be the case if<br>
&nbsp;there is a running request which takes more than a second or two to return.<br>
  执行异步请求,即在自己的线程中运行它。没有自动序列化op<br>
  属性访问,这意味着在执行线程运行时,所有相关的属性<br>
  TCustomRESTClient和TCustomRESTRequest实例不应该触及从其他线程(包括主线程)<br>
  移动平台上使用ExecuteAsync是强烈推荐。iOS(和可能Android)<br>
  终止应用程序如果认为主线程是反应迟钝,如果这将是如此<br>
  有一个请求,需要超过一两秒钟返回。</p>
<p>&nbsp;摘要说明:<br>
&nbsp;The idea behind this is that the UI runs in the main thread and mobile devices should respond to user<br>
&nbsp;interaction basically immediately. Sluggish behaviour (caused by blocking the main thread) is considered<br>
&nbsp;unacceptable on these small devices.<br>
  背后的想法是,用户界面运行在主线程和移动设备应该响应用户<br>
  互动基本上立即。缓慢的行为(阻塞主线程所致)<br>
  这些小设备上不可接受。</p>
<p>&nbsp;参数: name=ARequest<br>
&nbsp;The request to be executed 要执行的请求<br>
&nbsp;:参数结束<br>
&nbsp;参数: name=ACompletionHandler<br>
&nbsp;An anonymous method that will be run after the execution completed<br>
execute执行完成后的1个一个匿名方法</p>
<p>&nbsp;参数: name=ASynchronized<br>
&nbsp;Specifies if ACompletioHandler will be run in the main thread's (True) or execution thread's (False) context<br>
如果指定了ACompletioHandler,它将运行在主线程(True),否则它在执行线程的上下文运行(False)</p>
<p>&nbsp;参数: name=AFreeThread<br>
&nbsp;If True, then the execution thread will be freed after it completed<br>
如果True,那么运行完成后执行线程将被释放</p>
<p>&nbsp;参数: name=ACompletionHandlerWithError<br>
&nbsp;An anonymous method that will be run if an exception is raised during execution<br>
在执行期间如果抛出异常,这个一个匿名方法将被执行</p>
<p>&nbsp;返回值:<br>
&nbsp;Returns a reference to the execution thread. Should only be used if AFreeThread=False,&nbsp;<br>
&nbsp;as other wise the reference may get invalid unexpectedly.<br>
  返回对执行线程的引用。只用于参数AFreeThread = False,否则<br>
  返回的这个引用可能会意外的无效。</p>
<p><span style="color: rgba(51, 153, 234, 1)"><strong>2.10、应用案例:</strong></span></p>
<p>&nbsp; ///&lt;<span style="color: rgba(229, 121, 182, 1)"><strong>summary</strong></span>&gt;系统REST.Client单元Rest请求Web服务并返回Json数据:&lt;/summary&gt;<br>
&nbsp; &nbsp; /// &lt;param name="AParams"&gt;:参数:RESTRequest的请求参数名的动态数组:TArray即:TStringDynArray: 参考:System.IOUtils下的函数的初始化及实现方法:TDirectory.DoGetFiles.&lt;/param&gt;<br>
&nbsp; &nbsp; /// &lt;param name="AParamsValue"&gt;:参数:RESTRequest的请求参数值的动态数组.&lt;/param&gt;<br>
&nbsp; &nbsp; /// &lt;param name="ABaseUrl"&gt;:参数:RESTClient的URL资源的位置:即URL的第1段:BaseUrl://:最后1个"/"可带可不带:比如:http://www.cpuofbs.com:8080/或http://www.cpuofbs.com:8080均可:<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ///但不能重复"/":http://www.cpuofbs.com:8080//是错误的.<br>
&nbsp; &nbsp; /// &lt;/param&gt;<br>
&nbsp; &nbsp; /// &lt;param name="AResource"&gt;:参数:RESTRequest的服务器端方法函数(函数名及其参数名列表):即URL的第2段:Resource,比如:'getRecCountOnContitions/{pWhereGroupHavingEtc}/{pDataObject}'<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ///前缀"/"可带可不带:比如:getRecCountOnContitions/{pWhereGroupHavingEtc}/{pDataObject}<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ///或/getRecCountOnContitions/{pWhereGroupHavingEtc}/{pDataObject}'均可:前缀"/"可重复.<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ///每个参数名需要用{}括起来; 多个参数名用"/"分割开来。<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ///若用浏览器地址显式的rmGET数据,使用参数的数值而非参数名,表达为比如:http://www.cpuofbs.com:8080/datasnap/rest/TServerMethods1/getRecCountOnContitions/where (1=1)/PosBill<br>
&nbsp; &nbsp; /// &lt;/param&gt;<br>
&nbsp; &nbsp; /// &lt;param name="AMethod"&gt;:参数:RESTRequest的请求服务器端资源的类型(方法):uses REST.Types:rmPOST发送对象到服务器 rmPUT更新已存在或发送新的服务器对象<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ///rmGET检索并取回服务器对象 rmDELETE删除服务器已寻在对象 rmPATCH打补丁更新服务器上的Jsonpairs.<br>
&nbsp; &nbsp; /// &lt;/param&gt;<br>
&nbsp; &nbsp; /// &lt;param name="ModeAsyncOrSync"&gt;:参数:RESTRequest的请求执行的同步或异步模式:<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ///:=Async异步模式(默认);=sync同步模式<br>
&nbsp; &nbsp; /// &lt;/param&gt;<br>
&nbsp; &nbsp; /// &lt;param name="ADialogService"&gt;:参数:为主线程传入1个对话框服务提供主线程调用:<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ///:=(默认nil)<br>
&nbsp; &nbsp; /// &lt;/param&gt;<br>
&nbsp; &nbsp; /// &lt;returns&gt;:返回值:RESTRequest服务器端的方法返回的JSonValue:&lt;/returns&gt;<br>
&nbsp; <span style="color: rgba(229, 121, 182, 1)">function <strong>RestWebService</strong></span>(<br>
&nbsp; &nbsp; var AParams:TArray&lt;system.string&gt;;//:即:TStringDynArray: 参考:System.IOUtils下的函数的初始化及实现方法:TDirectory.DoGetFiles<br>
&nbsp; &nbsp; var AParamsValue:TArray&lt;system.string&gt;;<br>
&nbsp; &nbsp; const ABaseUrl:string='';<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AResource:string='';<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AMethod:TRESTRequestMethod=rmGET;<br>
&nbsp; &nbsp; const ModeAsyncOrSync:string='Async';<br>
&nbsp; &nbsp; const ADialogService:TDialogService=nil<br>
&nbsp; &nbsp; ):string;//:返回的JSon作为String后需要解析</p>
<p><span style="color: rgba(229, 121, 182, 1)"><strong>implemention</strong></span></p>
<p>&nbsp; &nbsp; <span style="color: rgba(229, 121, 182, 1)">function</span> <span style="color: rgba(229, 121, 182, 1)"><strong>RestWebService</strong></span>(<br>
&nbsp; &nbsp; &nbsp; var AParams:TArray&lt;system.string&gt;;//:即:TStringDynArray: 参考:System.IOUtils下的函数的初始化及实现方法:TDirectory.DoGetFiles<br>
&nbsp; &nbsp; &nbsp; var AParamsValue:TArray&lt;system.string&gt;;<br>
&nbsp; &nbsp; &nbsp; const ABaseUrl:string='';<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AResource:string='';<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AMethod:TRESTRequestMethod=rmGET;<br>
&nbsp; &nbsp; &nbsp; const ModeAsyncOrSync:string='Async';<br>
&nbsp; &nbsp; &nbsp; const ADialogService:TDialogService=nil<br>
&nbsp; &nbsp; ):string;<span style="color: rgba(229, 121, 182, 1)"><strong>//:返回的JSon作为String后需要解析</strong></span><br>
&nbsp; &nbsp; var<br>
&nbsp; &nbsp; &nbsp; LRESTClient: TRESTClient;<br>
&nbsp; &nbsp; &nbsp; LRESTRequest: TRESTRequest;<br>
&nbsp; &nbsp; &nbsp; LRESTResponse: TRESTResponse;<br>
&nbsp; &nbsp; &nbsp; LParamsCount:Integer;<br>
&nbsp; &nbsp; &nbsp; LEncoding:TEncoding;<br>
&nbsp; &nbsp; &nbsp; LResultStr:string;<br>
&nbsp; &nbsp; &nbsp; LTWaitResult:Cardinal;<br>
&nbsp; &nbsp; &nbsp; LThread:TThread;<br>
&nbsp; &nbsp; &nbsp; LRestReqErr:ERequestError; &nbsp;//:异常类:uses Rest.Types<br>
&nbsp; &nbsp; &nbsp; LRestReqStatusCode:Integer; //:异常响应状态码:默认0:正常值200<br>
&nbsp; &nbsp; &nbsp; LRestReqStatusText:string; &nbsp;//:异常响应状态文本:默认''<br>
&nbsp; &nbsp; begin<br>
&nbsp; &nbsp; &nbsp; <span style="color: rgba(229, 121, 182, 1)"><strong>//1、判断参数的完整性和一致性:</strong></span><br>
&nbsp; &nbsp; &nbsp; if (ABaseUrl.Trim='')<br>
&nbsp; &nbsp; &nbsp; &nbsp; or (AResource.Trim='')<br>
&nbsp; &nbsp; &nbsp; &nbsp; or (Length(AParams)&lt;&gt;Length(AParamsValue))<br>
&nbsp; &nbsp; &nbsp; &nbsp; or ( &nbsp;(UpperCase(ModeAsyncOrSync)&lt;&gt;'ASYNC')<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; and (UpperCase(ModeAsyncOrSync)&lt;&gt;'SYNC') &nbsp;) then<br>
&nbsp; &nbsp; &nbsp; begin<br>
&nbsp; &nbsp; &nbsp; &nbsp; Result:='';<br>
&nbsp; &nbsp; &nbsp; &nbsp; Exit;<br>
&nbsp; &nbsp; &nbsp; end;<br>
&nbsp; &nbsp; &nbsp; <span style="color: rgba(229, 121, 182, 1)"><strong>//2、设置Rest组件参数:</strong></span><br>
&nbsp; &nbsp; &nbsp; LRESTClient:= TRESTClient.Create(nil);<br>
&nbsp; &nbsp; &nbsp; LRESTClient.ResetToDefaults;<br>
&nbsp; &nbsp; &nbsp; LRESTClient.BaseURL:=ABaseUrl;//:重要 :设置服务器方法的资源位置<br>
&nbsp; &nbsp; &nbsp; LRESTResponse:= TRESTResponse.Create(nil);<br>
&nbsp; &nbsp; &nbsp; LRESTResponse.ResetToDefaults;<br>
&nbsp; &nbsp; &nbsp; //LRESTResponse.ContentType:='application/json';<br>
&nbsp; &nbsp; &nbsp; LRESTRequest:= TRESTRequest.Create(nil);<br>
&nbsp; &nbsp; &nbsp; LRESTRequest.ResetToDefaults;<br>
&nbsp; &nbsp; &nbsp; LRESTRequest.Client:=LRESTClient;<br>
&nbsp; &nbsp; &nbsp; LRESTRequest.Method:=AMethod;<br>
&nbsp; &nbsp; &nbsp; //LRESTRequest.SynchronizedEvents:=false;//:不要同步事件<br>
&nbsp; &nbsp; &nbsp; LRESTRequest.Resource:=AResource;//:重要:设置请求RESTRequest的服务器方法资源:方法函数名<br>
&nbsp; &nbsp; &nbsp; LRESTRequest.Response:=LRESTResponse;<br>
&nbsp; &nbsp; &nbsp; if Length(AParams)&gt;0 then //:如果有参数<br>
&nbsp; &nbsp; &nbsp; begin<br>
&nbsp; &nbsp; &nbsp; &nbsp; LRESTRequest.Params.Clear;<br>
&nbsp; &nbsp; &nbsp; &nbsp; LEncoding:=TEncoding.GetEncoding('UTF8');<br>
&nbsp; &nbsp; &nbsp; &nbsp; for LParamsCount := 0 to Length(AParams)-1 do<br>
&nbsp; &nbsp; &nbsp; &nbsp; begin //重要:设置请求RESTRequest的参数(如果有的话):<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AParams:=LEncoding.GetString(LEncoding.GetBytes(AParams));<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AParamsValue:=LEncoding.GetString(LEncoding.GetBytes(AParamsValue));<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: rgba(229, 121, 182, 1)"><strong>//:2.1、请求方法Method为POST时:TRESTRequestMethod.rmPOST</strong></span><br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:若参数及其参数值含中文<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:应当将参数及其参数值TEncoding.UTF8:<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:或:<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //AParams:=TIdURI.ParamsEncode(AParams, IndyTextEncoding_UTF8);<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:TIdURI: uses IdURI ;IndyTextEncoding_UTF8: uses IdGlobal<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /<span style="color: rgba(229, 121, 182, 1)"><strong>/:2.2、请求参数数值应与被调用的服务器函数的参数类型相一致:</strong></span><br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:为简便易用,服务器函数的参数约定均设置成string:<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:便于处理TDatetime和Boolean数据类型<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRESTRequest.AddParameter(<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AParams,<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AParamsValue,<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pkURLSEGMENT);<br>
&nbsp; &nbsp; &nbsp; &nbsp; end;<br>
&nbsp; &nbsp; &nbsp; end;<br>
&nbsp; &nbsp; &nbsp; <span style="color: rgba(229, 121, 182, 1)"><strong>//3、执行Rest请求RESTRequest并返回响应结果RESTResponse:</strong></span><br>
&nbsp; &nbsp; &nbsp; <strong><span style="color: rgba(229, 121, 182, 1)">//异步执行</span></strong>案例:<br>
&nbsp; &nbsp; &nbsp; if UpperCase(ModeAsyncOrSync)='ASYNC' then<br>
&nbsp; &nbsp; &nbsp; begin<br>
&nbsp; &nbsp; &nbsp; &nbsp; LThread:=(<br>
&nbsp; &nbsp; &nbsp; &nbsp; LRESTRequest.ExecuteAsync(<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; procedure<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LResultStr:=LRESTResponse.Content;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //产生请求异常的响应结果:<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRestReqStatusCode:=200; //:正确的返回<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRestReqStatusText:='OK';//:正确的返回<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRestReqErr:=ERequestError.Create(LRestReqStatusCode,LRestReqStatusText,LResultStr);<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end,<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; true,<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; false, //:释放执行线程<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; procedure (ExceptionObject:TObject) &nbsp;//Sender:TObject<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; begin &nbsp;//异常:<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if LRestReqStatusCode&lt;&gt;200 then //:如果请求返回异常的响应状态码<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ExceptionObject is Exception then<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LResultStr:='{"result":['+IntToStr(LRestReqStatusCode)+']}';<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //代表:'请求的资源或参数错误'导致不返回任何结果;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; //LResultStr:='{"result":}';//代表:'请求的资源或参数错误'导致不返回任何结果;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; //Application.ProcessMessages;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//raise Exception.Create('请求的资源或参数错误');<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//:异常捕获类:ERESTException:Exception:uses REST.Types<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; //:常规方法:捕获不了异常,只能通过上述ERESTException.StatusCode传给<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; //:LResultStr传递的返回值给客户端主线程来提示<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end<br>
&nbsp; &nbsp; &nbsp; &nbsp; ) as TThread);<br>
&nbsp; &nbsp; &nbsp; &nbsp; LTWaitResult:=LThread.WaitFor; &nbsp;//TWaitResult<br>
&nbsp; &nbsp; &nbsp; &nbsp; if LTWaitResult=0 then<br>
&nbsp; &nbsp; &nbsp; &nbsp; begin<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Result:=LResultStr;//:返回Json格式字符串<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //4、释放Rest组件:<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRESTClient.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRESTRequest.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRESTResponse.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LEncoding.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LThread.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; end else<br>
&nbsp; &nbsp; &nbsp; &nbsp; begin<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Application.ProcessMessages;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise Exception.Create('请求的资源或参数错误');<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:异常捕获不了,只能通过返回值给客户端主线程来提示<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:故而此段代码无意义!<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Result:=LResultStr;//:返回Json格式字符串<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //4、释放Rest组件:<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRESTClient.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRESTRequest.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRESTResponse.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LEncoding.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LThread.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>
&nbsp; &nbsp; &nbsp; &nbsp; end;<br>
&nbsp; &nbsp; &nbsp; end else<br>
&nbsp; &nbsp; &nbsp; if UpperCase(ModeAsyncOrSync)='SYNC' then<br>
&nbsp; &nbsp; &nbsp; begin <span style="color: rgba(229, 121, 182, 1)"><strong>//同步执行:</strong></span><br>
&nbsp; &nbsp; &nbsp; &nbsp; try<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRESTRequest.Execute;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LResultStr:=LRESTResponse.Content;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //产生请求异常的响应结果:<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRestReqStatusCode:=200; //:正确的返回<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRestReqStatusText:='OK';//:正确的返回<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRestReqErr:=ERequestError.Create(LRestReqStatusCode,LRestReqStatusText,LResultStr);<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; except<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if LRestReqStatusCode&lt;&gt;200 then //:如果请求返回异常的响应状态码<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ExceptionObject is Exception then<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LResultStr:='{"result":['+IntToStr(LRestReqStatusCode)+']}';<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //代表:'请求的资源或参数错误'导致不返回任何结果;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; //LResultStr:='{"result":}';//代表:'请求的资源或参数错误'导致不返回任何结果;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; //Application.ProcessMessages;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//raise Exception.Create('请求的资源或参数错误');<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//:异常捕获类:ERESTException:Exception:uses REST.Types<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; //:常规方法:捕获不了异常,只能通过上述ERESTException.StatusCode传给<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; //:LResultStr传递的返回值给客户端主线程来提示<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; end;<br>
&nbsp; &nbsp; &nbsp; &nbsp; finally<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Result:=LResultStr;//:返回Json格式字符串<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //4、释放Rest组件:<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRESTClient.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRESTRequest.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRESTResponse.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LEncoding.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRestReqErr.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; end;</p>
<p>&nbsp; &nbsp; &nbsp; end;<br>
&nbsp; &nbsp; &nbsp; //其它说明:<br>
&nbsp; &nbsp; &nbsp; //REST.Client控件从服务器Rest获得数据集到客户端适配数据集:<br>
&nbsp; &nbsp; &nbsp; //LRESTResponseDataSetAdapter.Response:= LRESTResponse;<br>
&nbsp; &nbsp; &nbsp; //LRESTResponseDataSetAdapter.Dataset:= LFDMemTable;</p>
<p>&nbsp; &nbsp; end;</p>
<p><span style="color: rgba(51, 153, 234, 1)"><strong>2.11、调用方法:</strong></span></p>
<p>&nbsp; &nbsp; procedure TfmxRestAndRestJson.Label5Click(Sender: TObject);<br>
&nbsp; &nbsp; //Rest记录数: https://www.cpuofbs.com:8080/datasnap/rest/TServerMethods1/getRecCountOnContitions/PosBill/where (1=1)<br>
&nbsp; &nbsp; var<br>
&nbsp; &nbsp; &nbsp; LResponseContent:string;<br>
&nbsp; &nbsp; &nbsp; LRecordCount:Integer;<br>
&nbsp; &nbsp; &nbsp; LJO:TJsonObject;<br>
&nbsp; &nbsp; &nbsp; AParams:<strong>TArray&lt;system.string&gt;;//:即:TStringDynArray;</strong><br>
&nbsp; &nbsp; &nbsp; AParamsValue:TStringDynArray;<br>
&nbsp; &nbsp; begin<br>
&nbsp; &nbsp; &nbsp; TabControl1.ActiveTab:=TabItem1;<br>
&nbsp; &nbsp; &nbsp; LRecordCount:=0;<br><strong>&nbsp; &nbsp; &nbsp; &nbsp; //TArray&lt;system.string&gt;动态数组初始化的方法:</strong><br>
&nbsp; &nbsp; &nbsp; AParams := nil; &nbsp;AParamsValue := nil;<br>
&nbsp; &nbsp; &nbsp; SetLength(AParams,2);<br>
&nbsp; &nbsp; &nbsp; SetLength(AParamsValue,2);<br><strong>&nbsp; &nbsp; &nbsp; &nbsp; //:动态数组不设置长度进行赋值会报错:</strong><br>
&nbsp; &nbsp; &nbsp; AParams:='ATableOrViewName';<br>
&nbsp; &nbsp; &nbsp; AParams:='ASqlWhereEtc';<br>
&nbsp; &nbsp; &nbsp; AParamsValue:='PosBill';<br>
&nbsp; &nbsp; &nbsp; AParamsValue:='where (1=1)';//'where (corp_name=''张尚书_厂部'')';<br>
&nbsp; &nbsp; &nbsp; try<br>
&nbsp; &nbsp; &nbsp; &nbsp; try<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LResponseContent:=<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: rgba(229, 121, 182, 1)"><strong>RestWebService</strong></span>(<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AParams,<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AParamsValue,<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'https://www.cpuofbs.com:8080/datasnap/rest/TServerMethods1/',<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:最后"/"个/可带可不带<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '/getRecCountOnContitions/{ATableOrViewName}/{ASqlWhereEtc}',<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:前缀"/"可带可不带<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TRESTRequestMethod.rmGET,<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //:请求方式TRESTRequestMethod不同于请求参数的种类:<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //TRESTRequestParameterKind.pkGETorPOST TRESTRequestParameterKind.pkURLSEGMENT<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'sync'<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ); //:uses myFuc_Client;<br>
&nbsp; &nbsp; &nbsp; &nbsp; except<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AParams := nil; &nbsp;AParamsValue := nil;<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise Exception.Create('请求的资源或参数错误');<br>
&nbsp; &nbsp; &nbsp; &nbsp; end;<br>
&nbsp; &nbsp; &nbsp; finally<br>
&nbsp; &nbsp; &nbsp; &nbsp; //:对上述返回udeRESTResponse.Content解析:<br>
&nbsp; &nbsp; &nbsp; &nbsp; LJO:=(TJsonObject.ParseJSONValue(LResponseContent) as TJsonObject);<br>
&nbsp; &nbsp; &nbsp; &nbsp; try<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LRecordCount:=(( LJO.GetValue('result') as TJsonArray).Items as TJsonNumber).AsInt;<br>
&nbsp; &nbsp; &nbsp; &nbsp; finally<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LJO.Free;<br>
&nbsp; &nbsp; &nbsp; &nbsp; end;<br>
&nbsp; &nbsp; &nbsp; &nbsp; Memo1.Lines.Clear;<br>
&nbsp; &nbsp; &nbsp; &nbsp; Memo1.Lines.BeginUpdate;<br>
&nbsp; &nbsp; &nbsp; &nbsp; Memo1.Lines.Add('Rest响应内容:'+LResponseContent);<br>
&nbsp; &nbsp; &nbsp; &nbsp; Memo1.Lines.Add('记录数:'+IntToStr(LRecordCount));<br>
&nbsp; &nbsp; &nbsp; &nbsp; Memo1.Lines.EndUpdate;<br>
&nbsp; &nbsp; &nbsp; end;<br>
&nbsp; &nbsp; end;</p>
<p><strong>执行结果:</strong></p>
<p style="text-align: center"><img alt="" class="has lazyload" data-src="https://img-blog.csdnimg.cn/20200209224712164.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p style="text-align: center"><img alt="" class="has lazyload" data-src="https://img-blog.csdnimg.cn/2020020922492796.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p>&nbsp;</p>
<p><strong>若服务未启动或网络异常:</strong></p>
<p style="text-align: center"><img alt="" class="has lazyload" data-src="https://img-blog.csdnimg.cn/20200209225050431.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p style="text-align: center"><img alt="" class="has lazyload" data-src="https://img-blog.csdnimg.cn/20200210185734102.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<h3><span style="color: rgba(51, 153, 234, 1)"><strong>三、Indy技术体系: IdHTTP;&nbsp;IdFTP;&nbsp; IdSSLOpenSSL;&nbsp; &nbsp;IdCookieManager;&nbsp;&nbsp;&nbsp;IdCompressorZLib;&nbsp;&nbsp;IdInterceptThrottler;&nbsp;&nbsp;&nbsp;IdInterceptSimLog;&nbsp;&nbsp;</strong></span></h3>
<p><strong>非DX原生的:来源于第三方Indy</strong></p>
<p><strong><span style="color: rgba(243, 59, 69, 1)">依赖:组件及其提供方的OEM开发工具的版本。</span>依赖于不同操作系统下的库文件(</strong><strong>libeay32、ssleay32;libeay64、ssleay64;libssl.so、libcrypto.so;libssl.a、libcrypto.a</strong><strong>)的更新:WIndows 下的.dll动态</strong><strong>库</strong><strong>文件,Android下的.so</strong><strong>库</strong><strong>文件,IOS下.a静态库文件,而且还需要分区32位及64位操作系统下不同的</strong><strong>库文件</strong></p>
<p><strong><span style="color: rgba(243, 59, 69, 1)">适用于:</span>1、服务器端Https服务的第三方SSL证书的导入和验证,2、服务器端的SSL客制化证书的生成和签发</strong></p>
<p><strong><span style="color: rgba(243, 59, 69, 1)">弱势:</span>跨平台客户端的SSL验证和Https访问,可以用,但需分平台且受制组件的版本,分发(发布)时较麻烦而已!&nbsp;</strong></p>
<p><strong><span style="color: rgba(243, 59, 69, 1)">优势:</span>资格最老的网络组件提供商,协议层很强大(是delphi Datasnap (Rest)Server的</strong><strong>Web.HTTPApp(协议)、Web.WebReq(web请求)、Web.WebBroker(web代理)的桥接底层,其它不依赖它);网络方面技术面面俱到,类库庞大,一直为delphi内置组件库</strong></p>
<p>&nbsp; &nbsp; IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;&nbsp;<span style="color: rgba(229, 121, 182, 1)"><strong> //: 处理https(协议层)的OpenSSL的方式</strong></span><br>
&nbsp; &nbsp; IdInterceptThrottler1: TIdInterceptThrottler;<br>
&nbsp; &nbsp; IdInterceptSimLog1: TIdInterceptSimLog;<br>
&nbsp; &nbsp; IdCookieManager1: TIdCookieManager;<br>
&nbsp; &nbsp; IdCompressorZLib1: TIdCompressorZLib;&nbsp;&nbsp;<strong>//: 处理压缩解压</strong></p>
<p>C:\Program Files (x86)\Embarcadero\Studio\20.0\source\Indy10\Protocols</p>
<p><strong>案例1:&nbsp;</strong>&nbsp;D:\delphiXEDev\HttpUpLoadAndDownLoad\<strong>IdHttpDownLoad</strong></p>
<p style="text-align: center"><img alt="" class="has lazyload" width="800" data-src="https://img-blog.csdnimg.cn/20200201182131658.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p><strong>案例2:</strong>&nbsp;&nbsp;D:\delphiXEDev\OpenSSL\OpenSSL-delphi编程Https\delphi编程HttpsDownload\Win64\Debug</p>
<p><strong>网页数据抓取(抓包、网页爬取、爬虫):&nbsp;</strong></p>
<p style="text-align: center"><img alt="" class="has lazyload" data-src="https://img-blog.csdnimg.cn/20200201182306652.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3B1bGxlZHVw,size_16,color_FFFFFF,t_70"></p>
<p>&nbsp;</p>
<h3><span style="color: rgba(51, 153, 234, 1)">四、浏览器客户端技术JavaScript+jQuery(Mobile)+Http DOM+Ajax</span></h3>
<h3><span style="color: rgba(243, 59, 69, 1)">非常强大,目前主流技术!</span></h3>
<p><strong>跨平台、跨操作系统、跨语言</strong></p>
<p><strong>4.1、篇幅所限,不再赘述!学习的话,可参考:</strong></p>
<p>(以下转,感谢博主!)</p>
<p><strong>最权威:<span style="color: rgba(229, 121, 182, 1)">官方产品经理:Marco Cantù的 《REST Servers in Delphi XE Using DataSnap》</span></strong>,网上的中文翻译版.pdf :</p>
<p>https://download.csdn.net/download/weixin_42404994/10742572</p>
<p>《REST Servers in Delphi XE Using DataSnap》<strong>源码下载:</strong>REST Servers in Delphi XE Using DataSnap.CodeSample.rar</p>
<p>https://download.csdn.net/download/chunyangsuhao/11429142</p>
<p>Delphi 10.3 Web应用开发B/S框架介绍(一):uniGUI:</p>
<p>https://blog.csdn.net/xyzhan/article/details/86527802</p>
<p>Delphi 10.3 Web应用开发B/S框架介绍(二):IntraWeb 17:</p>
<p>https://blog.csdn.net/xyzhan/article/details/86528302</p>
<p>Bootstrap中文版(响应式):</p>
<p>https://www.bootcss.com/</p>
<p>Bootstrap+H5+Css3+js网页前端可视化布局在线生成工具:</p>
<p>https://www.bootcss.com/p/layoutit/</p>
<p>w3school:Web前端技术学习大全:</p>
<p>https://www.w3school.com.cn/index.html&nbsp; 其中内容如下:</p>
<p>&nbsp; &nbsp; HTML及H5+CSS3教程 + 浏览器脚本 + 服务器脚本 + XML教程<br>
&nbsp; &nbsp; 其中,浏览器脚本:<br>
&nbsp; &nbsp; JavaScript、HTML DOM、jQuery、jQuery Mobile、AJAX、JSON、DHTML、E4X、WMLScript</p>
<p><strong>4.2、附:delphi App中调用JavaScript方法,供学习参考::</strong></p>
<p>(以下转,感谢博主!)</p>
<p>基于HTML模板和JSON数据的JavaScript交互:</p>
<p>https://blog.csdn.net/u013558749/article/details/52445049</p>
<p>REST Datasnap服务端与javascript客户端实现:</p>
<p>https://blog.csdn.net/a00553344/article/details/51719643</p>
<p>delphi与javascript交互:</p>
<p>https://download.csdn.net/download/qq_30347073/9162031</p>
<p>解决Delphi(FireMonkey)Andorid,IOS移动应用WebBrowser与JavaScript交互问题:</p>
<p>http://blog.sina.com.cn/s/blog_72eb56aa0102xkgg.html</p>
<p>Firemonkey扩展增强:Android 浏览器执行JavaScript获取结果及JavaScript调用本地方法:</p>
<p>https://blog.csdn.net/tht2009/article/details/53996177</p>
<p>Windows下:</p>
<p>Delphi 中调用JS文件中的方法:</p>
<p>https://www.cnblogs.com/limingliyu/p/5658767.html</p>
<p>delphi中执行javascript代码:</p>
<p>http://www.delphitop.com/html/wenjian/2780.html</p>
<p><strong>4.3、其它:</strong></p>
<p>JS清除缓存的几种方法:</p>
<p>https://blog.csdn.net/weixin_42983021/article/details/92833944</p><br><br>
来源:https://www.cnblogs.com/hjsofware/p/12293964.html
頁: [1]
查看完整版本: delphi Restful:客户端实现的四种方式及其比较