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

delphi Restful:客户端实现的四种方式

摘要:转载自https://blog.csdn.net/pulledup/article/details/104132753


一、NetHTTP技术体系:? TNetHTTPClient;?? TNetHTTPRequest
二、REST技术体系:
???????TRESTClient; TRESTRequest; TRESTResponse; TRESTResponseDataSetAdapter
三、Indy技术体系:IdHTTP + IdSSLOpenSSL?
四、浏览器客户端技术体系:JavaScript+jQuery(Mobile)+Http DOM+Ajax

?

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

?

一、NetHTTP技术体系:

System.Net.HttpClient;??System.Net.URLClient;??System.Net.FileClient;?

System.Net.Mime;??System.Net.Socket;??System.Net.HttpClientComponent;??

非常强大!

优势:

? ? DX原生的:仅取决于操作系统,操作系统升级后,部署及其代码不会受到任何影响;不受组件的版本影响;可方便地Rest

? ? 既能很好的支持TSession会话方式的基本鉴权,又能很好的支持AccessToken访问令牌方式或代码方式的高级鉴权,有专门的非可视化鉴权类(TCertificateList = class(TList<TCertificate>);)支持,需要自己写代码去实现

? ? 异常处理:强大、方便。

属系统运行时刻库

C:\Program Files (x86)\Embarcadero\Studio\20.0\source\rtl\net?

对应的原生组件:? ?

? ? NetHTTPClient1: TNetHTTPClient;
? ? NetHTTPRequest1: TNetHTTPRequest;

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

既可直接使用组件

NetHTTPClient1: TNetHTTPClient;??? ? NetHTTPRequest1: TNetHTTPRequest;

也可以不使用组件,而动态产生

官方案例1:同步多线程文件分段下载:??

? ? D:\开发测试\Samples\Object Pascal\RTL\HttpDownload\HttpDownloadDemo.dproj

? ? C:\Users\Public\Documents\Embarcadero\Studio\20.0\Samples\Object Pascal\RTL\HttpDownload

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

官方案例2:异步单线程文件下载:??

? ? D:\开发测试\Samples\Object Pascal\RTL\HttpAsyncDownload\HttpAsyncDownloadDemo.dproj

? ? C:\Users\Public\Documents\Embarcadero\Studio\20.0\Samples\Object Pascal\RTL\HttpAsyncDownload

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

第三方案例3:HTTPClient的Rest方法获取Json数据&并行库未来&异步任务

? ? D:\开发测试\Samples\其它\myTestCode\DelphiCookbookThirdEdition\Chapter05\CODE\RECIPE07\

?

?

? ? var
? ? ? MainForm: TMainForm;

? ? implementation

? ? uses
? ? ? System.Net.HTTPClient, System.JSON
? ? ? , AsyncTask
? ? ? , Converters
? ? ? ;

? ? {$R *.dfm}

? ? const
? ? ? ACCESS_KEY = ‘58297a8c75e21d218b1da2c610b6f62c‘;?

? ? ? ? //:Token鉴权思路:初次给常数,下载令牌文件,再次登录验证令牌办法的合法性

? ? procedure TMainForm.FormCreate(Sender: TObject);
? ? var ListPair:TStringList; ListObject:TStringList;
? ? ? ? ? LStrRespContent:string;
? ? ? ? //:以上我加的
? ? //泛型异步任务:Rest调用数据、UI加载结果处理异常:FormCreate事前获取币种,保存到TStringList中:
? ? begin
? ? ? Async.Run<TStringList>(
? ? ? ? function: TStringList??? //:异步任务:匿名线程执行函数:
? ? ? ? var
? ? ? ? ? LHTTP: THTTPClient;
? ? ? ? ? LResp: IHTTPResponse;

? ? ? ? ? LJObj: TJSONObject;
? ? ? ? ? LJRates: TJSONObject;
? ? ? ? ? I: Integer;
? ? ? ? begin
? ? ? ? ? LHTTP := THTTPClient.Create;

? ? ? ? ? ? //:步骤1:THTTPClient实例化
? ? ? ? ? try
? ? ? ? ? ? LResp := LHTTP.Get(
? ? ? ? ? ? ??‘http://data.fixer.io/api/latest‘ //:baseURL:TURI的baseURL部分:包括Scheme(协议https://等)+Path(路径)+Port(端口)等
? ? ? ? ? ? ??+‘?‘ ?//:FQuery:TURI查询指令部分
? ? ? ? ? ? ??+‘access_key=‘+ACCESS_KEY //:TURIParameters:TURI参数部分(TNameValuePair名称=数值的对,参数间用’&’分割)
? ? ? ? ? ? ? ? ? ? //:在本例:access_key该参数相当于Token鉴权方式
? ? ? ? ? ? );

? ? ? ? ? ? //:步骤2:THTTPClient获取URL的默认头定义的响应接口IHTTPResponse

? ? ? ? ? ? LStrRespContent:=LResp.ContentAsString(TEncoding.UTF8);

? ? ? ? ? ? //:步骤3:响应接口IHTTPResponse以UTF8编码获取响应结果的内容字符串

? ? ? ? ? ? LStrRespContent:=TConverters.JsonReformat(LStrRespContent,true);
? ? ? ? ? ? //:步骤4:格式化获取到的响应结果的内容字符串为缩进的JSon格式化的字符串
? ? ? ? ? ? ? //:(便于阅读和调试)

? ? ? ? ? ? LJObj := TJSONObject.ParseJSONValue (LStrRespContent) as TJSONObject;

? ? ? ? ? ? //:步骤5:解析:获取到的响应结果的JSon格式化的字符串:为JSON对象:

? ? ? ? ? ? try
? ? ? ? ? ? ? LJRates := LJObj.GetValue<TJSONObject>(‘rates‘);
? ? ? ? ? ? ? ListPair := TStringList.Create;
? ? ? ? ? ? ? ListObject:=TStringList.Create;
? ? ? ? ? ? ? ? //:我加的
? ? ? ? ? ? ? Result := TStringList.Create;
? ? ? ? ? ? ? for I := 0 to LJRates.Count - 1 do
? ? ? ? ? ? ? begin
? ? ? ? ? ? ? ? //ListPair.Add( LJRates.Pairs[I].JsonString.Value +‘ : ‘
? ? ? ? ? ? ? ? ? //+ LJRates.Pairs[I].JsonValue.ToString );
? ? ? ? ? ? ? ? ListObject.Add( LJRates.Pairs[I].JsonString.Value +‘=‘
? ? ? ? ? ? ? ? ? + LJRates.Pairs[I].JsonValue.ToString );
? ? ? ? ? ? ? ? ListPair.AddPair(LJRates.Pairs[I].JsonString.Value,
? ? ? ? ? ? ? ? ? LJRates.Pairs[I].JsonValue.ToString,
? ? ? ? ? ? ? ? ? ListObject );

? ? ? ? ? ? ? ? ? //:我加的
? ? ? ? ? ? ? ? Result.Add(LJRates.Pairs[I].JsonString.Value);
? ? ? ? ? ? ? end;
? ? ? ? ? ? ? Result.Sort;//:成功回调值TStringList索引排序
? ? ? ? ? ? finally
? ? ? ? ? ? ? LJObj.Free;
? ? ? ? ? ? end;
? ? ? ? ? finally
? ? ? ? ? ? LHTTP.Free;

? ? ? ? ? ? //:步骤7:释放THTTPClient实例
? ? ? ? ? end;
? ? ? ? end,
? ? ? ? procedure(const Strings: TStringList)
? ? ? ? begin? //:异步任务:主线程加载数据:

? ? ? ? ? ? //:步骤6:UI加载解析后的数据:
? ? ? ? ? Memo3.Clear;
? ? ? ? ? Memo3.Lines.BeginUpdate;
? ? ? ? ? Memo3.Lines.Add(LStrRespContent);
? ? ? ? ? ? //:加载经过格式化的响应内容字符串
? ? ? ? ? ? ? //:HTTP客户端Rest请求的JSon对象值(各币种对欧元)

? ? ? ? ? Memo3.Lines.EndUpdate;
? ? ? ? ? cbSymbol.Items.Assign(Strings);//:下拉框赋值
? ? ? ? ? Memo1.Lines.Clear; Memo1.Lines.BeginUpdate;
? ? ? ? ? //Memo1.Lines.Add( (ListPair.Objects[0] as TStrings).Text );
? ? ? ? ? Memo1.Lines.Add( ListPair.Text );
? ? ? ? ? //Memo1.Lines.Add( ListObject.Text );
? ? ? ? ? Memo1.Lines.EndUpdate;
? ? ? ? ? ? //:加载各币种对欧元的实时汇率:
? ? ? ? ? Memo2.Lines.Clear; Memo2.Lines.BeginUpdate;
? ? ? ? ? Memo2.Lines.Add( LStrRespContent ); Memo2.Lines.EndUpdate;
? ? ? ? ? ?//:我加的
? ? ? ? end,
? ? ? ? procedure(const ExceptParallel:Exception)
? ? ? ? begin??//:异步任务:异常处理:
? ? ? ? ? if ExceptParallel.Message.Trim<>‘‘ then
? ? ? ? ? begin
? ? ? ? ? ? ShowMessage(‘请求出错了‘);
? ? ? ? ? end;
? ? ? ? end

? ? ? ? );
? ? end;
?

二、REST技术体系:

? ? ? ?REST.Client;??REST.Response.Adapter;? ?REST.HttpClient;?REST.Types;

? ? ? ?REST.Json, REST.Json.Interceptors;?? REST.BindSource;? REST.Utils;?

? ? ? ?REST.Authenticator.Basic;???REST.Authenticator.OAuth;

TRESTClient的底层是THTTPClient: 继承关系如下->?TRESTHTTP ->?REST.Client->?THTTPClient.Create->??THTTPClient? ? ->???System.Net.HttpClient

DX原生的:仅取决于操作系统,操作系统升级后,部署及其代码不会受到任何影响;不受组件的版本影响;可方便地Rest

//:这一组Rest客户端组件只对返回Json数据有效,对流和Xml均无效:

强大,好用,简单!

优势:

1、REST.Json, REST.Json.Interceptors :体系中这套与Json的交互,既可用于客户端,也可用于服务器端

2、既能很好的支持TSession会话方式的基本鉴权,又能很好的支持AccessToken访问令牌方式或代码方式的高级鉴权,有专门的非可视化鉴权单元(REST.Authenticator.Basic和REST.Authenticator.OAuth)支持,需要自己写代码去实现

弱势:

如果网络异常或服务器程序未启动或服务器程序错误,异常,在处理异常方面麻烦一些,其异常类(ERequestError? :uses Rest.Types)功能比较简单!

C:\Program Files (x86)\Embarcadero\Studio\20.0\source\data\rest

? ? RESTClient1: TRESTClient;? ? ? ? ? ? ? ? ? ? //uses?REST.Client;
? ? RESTRequest1: TRESTRequest;? ? ? ? ? ?//uses?REST.Client;
? ? RESTResponse1: TRESTResponse;? ? ?//uses?REST.Client;?
? ? RESTResponseDataSetAdapter1: TRESTResponseDataSetAdapter;? /uses?REST.Response.Adapter;

? ? REST.BindSource? //:Rest客户端数据绑定源
? ? REST.Utils? //:Rest客户端实用工具:
? ? ? ? //:URIEncode、ExtractURLSegmentNames、ExtractGetParams、
? ? ? ? //:RESTComponentIsDesigning、TRESTFindDefaultComponent?
? ? REST.Authenticator.Basic? ? //:Rest客户端基本鉴权单元:TSession会话方式
? ? REST.Authenticator.OAuth? ?//:Rest客户端高级鉴权单元:AccessToken访问令牌方式或代码方式

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

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

Rest体系的客户端架构方案:

uses

? ClientModuleUnit1, //:我的客户端数据模块
? Converters
? ? //:我的Json到Bson的互转类、TBytes到String的互转类、JSon重新格式化、JSon到delphi代码转化、JSon到TJsonWriter代码转化、JSon到TJsonBuilder代码转化
? ? //:Converters:搜索路径:D:\PulledupO2O\myPublic\RTL\RTLSamples\Json

? , AsyncTask //: 我的异步任务单元

? ? //以下为系统类别:
? , System.Types,System.Variants,System.Classes
? , System.UITypes
? , System.SysUtils,System.IOUtils,System.StartUpCopy
? , System.Threading, System.SyncObjs //线程、任务;事件总线
? , System.Rtti//:系统运行时刻库(运行时的类型信息Run Time date Type Infomation):
? , System.NetEncoding ?//:系统网络编码的运行时刻库:编码加密、解码解密
? , System.Math //:系统数学函数库
? , system.hash //:系统自带的的Hash哈希单元
? , System.Devices //:系统设备描述单元
? //系统原生JSON类:
? , System.JSON.Types
? , System.JSONConsts
? , System.JSON.Utils
? , System.JSON ,System.JSON.Readers
? , System.JSON.Builders
? //引用泛型对象*<T>的单元:
? //, System.TypInfo ,System.Generics.Collections ,System.Generics.Defaults

? //Rest类:
? , REST.Response.Adapter, REST.Client //:REST客户端组件引用: ?//组件TRESTClient TRESTRequest TRESTResponse TRESTResponseDataSetAdapter的单元:

? , REST.Types//:Rest客户端请求的各种类型的常量、枚举的定义,异常捕获的定义
? , REST.Consts//:Rest客户端的运行是提示常量
? //Rest的以下体系中这套与Json的交互,既可用于客户端,也可用于服务器端:
? , REST.Json.Types //:REST.Json特殊类型的运行时刻库:日期、布尔的编组与解析
? , REST.Json.Interceptors
? ? //:Json这些数据类型拦截器:实现对时区、日期时间中的分段、
? ? ? //:数组中的局部字符串:转TListOfObjects = array of TObject及其反转
? ? ? //:字符串中的局部字符串:转TObject及其反转
? , REST.Json
? ? //:TJson类封装:将TObject对象转Json和Json格式的string,
? ? ? //:Json和Json格式的string转对象TObject,
? ? ? //:Json格式化(TStringBuilder规范化重写)及
? ? ? //:Json和Json格式的string规范化UTF8编码
? , REST.JsonReflect//:Json映射:数据对象与编组、转化:
? ? //:REST.JsonReflect来源于Data.DBXJSONReflect,只是它更轻量级.
? ? //:最重要是它不依赖于注入到中JSON对象的元数据.
? ? //:它的目的是“reflect映射”Json属性到TObject,反之亦然.
? ? ? //:这里所有JSON对象创建或处理均以“plain”的方式对待.
? ? ? ? //在本单元实现方式从设计的观点来看仍然是“粗糙”的,
? ? ? ? //:但会随着时间的推移得以改善(10.3应该完善啦)
? ? //重要:这里严重涉及RTTI,因此可能不能被禁用,必须引用System.RTTI.
? ? //目前不建议直接使用这个单元,因为它的接口可能随时间而改变.
? ? ? //:推荐使用REST.Json中的TJson类(或Data.DBXJSONReflect).
? ? //REST.Json中的接口是稳定的.
? ? ? //:10.0以前暂不建议直接使用它(10.3应该完善啦)
? ? //:可替代方案:使用以下两个JSon映射互转的封装:
? //数据库的JSon映射:数据对象与编组、转化:
? , Data.FireDACJSONReflect ?,Data.DBXJSONReflect
? , Data.DBXJSONCommon? //:数据库DBX的通用JSON
? // 数据库:字段列表、字段、对象字段、数据链接、数据源、字段选项、字段定义列表、索引列表定义:
? , Data.DB
? //Dbx数据压缩及过滤器:
? , Data.DbxCompressionFilter
? //数据绑定单元:
? , Data.Bind.Components ,Data.Bind.ObjectScope

官方案例1:

? ??D:\开发测试\Samples\Object Pascal\Database\RESTDemo

? ??C:\Users\Public\Documents\Embarcadero\Studio\20.0\Samples\Object Pascal\Database\RESTDemo

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

?适配JSon数据到客户端数据集:

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

官方案例2:

? ??D:\开发测试\Samples\Object Pascal\DataSnap\FireDACJSONReflect\sysClass\source\data\rest\restdebugger\RESTDebugger.dproj

? ??C:\Program Files (x86)\Embarcadero\Studio\20.0\source\data\rest\restdebugger\RESTDebugger.dproj

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

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

或者:

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

2.1、

--->默认值常量:

REST.Types;

? TCompletionHandler = TProc;
? TCompletionHandlerWithError = TProc<TObject>;

? TRESTObjectOwnership = (ooCopy, ooREST, ooApp);

? TRESTRequestParameterOption枚举

? TRESTRequestParameterOptions = set of TRESTRequestParameterOption;
? TRESTRequestParameterKind枚举

? ? pkGETorPOST
? ? pkURLSEGMENT
? ? pkREQUESTBODY
? ? pkQUERY

? DefaultRESTRequestParameterKind: TRESTRequestParameterKind = TRESTRequestParameterKind.pkGETorPOST;
? function RESTRequestParameterKindToString(const AKind: TRESTRequestParameterKind): string;
? function RESTRequestParameterKindFromString(const AKindString: string): TRESTRequestParameterKind;

2.2、

? ? type
? ? ? /// <summary>
? ? ? /// Content
? ? ? /// </summary>
? ? ? TRESTContentType = (ctNone, ctAPPLICATION_ATOM_XML, ctAPPLICATION_ECMASCRIPT, ctAPPLICATION_EDI_X12,
? ? ? ? ctAPPLICATION_EDIFACT, ctAPPLICATION_JSON, ctAPPLICATION_JAVASCRIPT, ctAPPLICATION_OCTET_STREAM, ctAPPLICATION_OGG,
? ? ? ? ctAPPLICATION_PDF, ctAPPLICATION_POSTSCRIPT, ctAPPLICATION_RDF_XML, ctAPPLICATION_RSS_XML, ctAPPLICATION_SOAP_XML,
? ? ? ? ctAPPLICATION_FONT_WOFF, ctAPPLICATION_XHTML_XML, ctAPPLICATION_XML, ctAPPLICATION_XML_DTD, ctAPPLICATION_XOP_XML,
? ? ? ? ctAPPLICATION_ZIP, ctAPPLICATION_GZIP, ctTEXT_CMD, ctTEXT_CSS, ctTEXT_CSV, ctTEXT_HTML, ctTEXT_JAVASCRIPT,
? ? ? ? ctTEXT_PLAIN, ctTEXT_VCARD, ctTEXT_XML, ctAUDIO_BASIC, ctAUDIO_L24, ctAUDIO_MP4, ctAUDIO_MPEG, ctAUDIO_OGG,
? ? ? ? ctAUDIO_VORBIS, ctAUDIO_VND_RN_REALAUDIO, ctAUDIO_VND_WAVE, ctAUDIO_WEBM, ctIMAGE_GIF, ctIMAGE_JPEG, ctIMAGE_PJPEG,
? ? ? ? ctIMAGE_PNG, ctIMAGE_SVG_XML, ctIMAGE_TIFF, ctMESSAGE_HTTP, ctMESSAGE_IMDN_XML, ctMESSAGE_PARTIAL, ctMESSAGE_RFC822,
? ? ? ? ctMODEL_EXAMPLE, ctMODEL_IGES, ctMODEL_MESH, ctMODEL_VRML, ctMODEL_X3D_BINARY, ctMODEL_X3D_VRML, ctMODEL_X3D_XML,
? ? ? ? ctMULTIPART_MIXED, ctMULTIPART_ALTERNATIVE, ctMULTIPART_RELATED, ctMULTIPART_FORM_DATA, ctMULTIPART_SIGNED,
? ? ? ? ctMULTIPART_ENCRYPTED, ctVIDEO_MPEG, ctVIDEO_MP4, ctVIDEO_OGG, ctVIDEO_QUICKTIME, ctVIDEO_WEBM, ctVIDEO_X_MATROSKA,
? ? ? ? ctVIDEO_X_MS_WMV, ctVIDEO_X_FLV, ctAPPLICATION_VND_OASIS_OPENDOCUMENT_TEXT,
? ? ? ? ctAPPLICATION_VND_OASIS_OPENDOCUMENT_SPREADSHEET, ctAPPLICATION_VND_OASIS_OPENDOCUMENT_PRESENTATION,
? ? ? ? ctAPPLICATION_VND_OASIS_OPENDOCUMENT_GRAPHICS, ctAPPLICATION_VND_MS_EXCEL,
? ? ? ? ctAPPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_SPREADSHEETML_SHEET, ctAPPLICATION_VND_MS_POWERPOINT,
? ? ? ? ctAPPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_PRESENTATIONML_PRESENTATION,
? ? ? ? ctAPPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_WORDPROCESSINGML_DOCUMENT, ctAPPLICATION_VND_MOZILLA_XUL_XML,
? ? ? ? ctAPPLICATION_VND_GOOGLE_EARTH_KML_XML, ctAPPLICATION_VND_GOOGLE_EARTH_KMZ, ctAPPLICATION_VND_DART,
? ? ? ? ctAPPLICATION_VND_ANDROID_PACKAGE_ARCHIVE, ctAPPLICATION_X_DEB, ctAPPLICATION_X_DVI, ctAPPLICATION_X_FONT_TTF,
? ? ? ? ctAPPLICATION_X_JAVASCRIPT, ctAPPLICATION_X_LATEX, ctAPPLICATION_X_MPEGURL, ctAPPLICATION_X_RAR_COMPRESSED,
? ? ? ? ctAPPLICATION_X_SHOCKWAVE_FLASH, ctAPPLICATION_X_STUFFIT, ctAPPLICATION_X_TAR, ctAPPLICATION_X_WWW_FORM_URLENCODED,
? ? ? ? ctAPPLICATION_X_XPINSTALL, ctAUDIO_X_AAC, ctAUDIO_X_CAF, ctIMAGE_X_XCF, ctTEXT_X_GWT_RPC, ctTEXT_X_JQUERY_TMPL,
? ? ? ? ctTEXT_X_MARKDOWN, ctAPPLICATION_X_PKCS12, ctAPPLICATION_X_PKCS7_CERTIFICATES, ctAPPLICATION_X_PKCS7_CERTREQRESP,
? ? ? ? ctAPPLICATION_X_PKCS7_MIME, ctAPPLICATION_X_PKCS7_SIGNATURE, ctAPPLICATION_VND_EMBARCADERO_FIREDAC_JSON);

? ? var
? ? ? DefaultRESTContentType: TRESTContentType = TRESTContentType.ctNone;

? ? const
? ? ? /// <summary>
? ? ? /// HTTP Content-Type (or MIME Types as per RFC 2046) header Definitions.
? ? ? /// </summary>
? ? ? /// <remarks>
? ? ? /// <para>
? ? ? /// See: http://tools.ietf.org/html/rfc2046
? ? ? /// </para>
? ? ? /// <para>
? ? ? /// Values collected from https://en.wikipedia.org/wiki/MIME_type
? ? ? /// </para>
? ? ? /// </remarks>

? ? ? CONTENTTYPE_NONE = ‘‘; // do not localize
? ? ? // Type Application
? ? ? CONTENTTYPE_APPLICATION_ATOM_XML = ‘application/atom+xml‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_ECMASCRIPT = ‘application/ecmascript‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_EDI_X12 = ‘application/EDI-X12‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_EDIFACT = ‘application/EDIFACT‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_JSON = ‘application/json‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_JAVASCRIPT = ‘application/javascript‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_OCTET_STREAM = ‘application/octet-stream‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_OGG = ‘application/ogg‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_PDF = ‘application/pdf‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_POSTSCRIPT = ‘application/postscript‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_RDF_XML = ‘application/rdf+xml‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_RSS_XML = ‘application/rss+xml‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_SOAP_XML = ‘application/soap+xml‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_FONT_WOFF = ‘application/font-woff‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_XHTML_XML = ‘application/xhtml+xml‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_XML = ‘application/xml‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_XML_DTD = ‘application/xml-dtd‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_XOP_XML = ‘application/xop+xml‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_ZIP = ‘application/zip‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_GZIP = ‘application/gzip‘; // do not localize
? ? ? // Type Text
? ? ? CONTENTTYPE_TEXT_CMD = ‘text/cmd‘; // do not localize
? ? ? CONTENTTYPE_TEXT_CSS = ‘text/css‘; // do not localize
? ? ? CONTENTTYPE_TEXT_CSV = ‘text/csv‘; // do not localize
? ? ? CONTENTTYPE_TEXT_HTML = ‘text/html‘; // do not localize
? ? ? CONTENTTYPE_TEXT_JAVASCRIPT = ‘text/javascript‘; // do not localize
? ? ? CONTENTTYPE_TEXT_PLAIN = ‘text/plain‘; // do not localize
? ? ? CONTENTTYPE_TEXT_VCARD = ‘text/vcard‘; // do not localize
? ? ? CONTENTTYPE_TEXT_XML = ‘text/xml‘; // do not localize
? ? ? // Type Audio
? ? ? CONTENTTYPE_AUDIO_BASIC = ‘audio/basic‘; // do not localize
? ? ? CONTENTTYPE_AUDIO_L24 = ‘audio/L24‘; // do not localize
? ? ? CONTENTTYPE_AUDIO_MP4 = ‘audio/mp4‘; // do not localize
? ? ? CONTENTTYPE_AUDIO_MPEG = ‘audio/mpeg‘; // do not localize
? ? ? CONTENTTYPE_AUDIO_OGG = ‘audio/ogg‘; // do not localize
? ? ? CONTENTTYPE_AUDIO_VORBIS = ‘audio/vorbis‘; // do not localize
? ? ? CONTENTTYPE_AUDIO_VND_RN_REALAUDIO = ‘audio/vnd.rn-realaudio‘; // do not localize
? ? ? CONTENTTYPE_AUDIO_VND_WAVE = ‘audio/vnd.wave‘; // do not localize
? ? ? CONTENTTYPE_AUDIO_WEBM = ‘audio/webm‘; // do not localize
? ? ? // Type Image
? ? ? CONTENTTYPE_IMAGE_GIF = ‘image/gif‘; // do not localize
? ? ? CONTENTTYPE_IMAGE_JPEG = ‘image/jpeg‘; // do not localize
? ? ? CONTENTTYPE_IMAGE_PJPEG = ‘image/pjpeg‘; // do not localize
? ? ? CONTENTTYPE_IMAGE_PNG = ‘image/png‘; // do not localize
? ? ? CONTENTTYPE_IMAGE_SVG_XML = ‘image/svg+xml‘; // do not localize
? ? ? CONTENTTYPE_IMAGE_TIFF = ‘image/tiff‘; // do not localize
? ? ? // Type Message
? ? ? CONTENTTYPE_MESSAGE_HTTP = ‘message/http‘; // do not localize
? ? ? CONTENTTYPE_MESSAGE_IMDN_XML = ‘message/imdn+xml‘; // do not localize
? ? ? CONTENTTYPE_MESSAGE_PARTIAL = ‘message/partial‘; // do not localize
? ? ? CONTENTTYPE_MESSAGE_RFC822 = ‘message/rfc822‘; // do not localize
? ? ? // Type Model (3D Models)
? ? ? CONTENTTYPE_MODEL_EXAMPLE = ‘model/example‘; // do not localize
? ? ? CONTENTTYPE_MODEL_IGES = ‘model/iges‘; // do not localize
? ? ? CONTENTTYPE_MODEL_MESH = ‘model/mesh‘; // do not localize
? ? ? CONTENTTYPE_MODEL_VRML = ‘model/vrml‘; // do not localize
? ? ? CONTENTTYPE_MODEL_X3D_BINARY = ‘model/x3d+binary‘; // do not localize
? ? ? CONTENTTYPE_MODEL_X3D_VRML = ‘model/x3d+vrml‘; // do not localize
? ? ? CONTENTTYPE_MODEL_X3D_XML = ‘model/x3d+xml‘; // do not localize
? ? ? // Type Multipart
? ? ? CONTENTTYPE_MULTIPART_MIXED = ‘multipart/mixed‘; // do not localize
? ? ? CONTENTTYPE_MULTIPART_ALTERNATIVE = ‘multipart/alternative‘; // do not localize
? ? ? CONTENTTYPE_MULTIPART_RELATED = ‘multipart/related‘; // do not localize
? ? ? CONTENTTYPE_MULTIPART_FORM_DATA = ‘multipart/form-data‘; // do not localize
? ? ? CONTENTTYPE_MULTIPART_SIGNED = ‘multipart/signed‘; // do not localize
? ? ? CONTENTTYPE_MULTIPART_ENCRYPTED = ‘multipart/encrypted‘; // do not localize
? ? ? // Type Video
? ? ? CONTENTTYPE_VIDEO_MPEG = ‘video/mpeg‘; // do not localize
? ? ? CONTENTTYPE_VIDEO_MP4 = ‘video/mp4‘; // do not localize
? ? ? CONTENTTYPE_VIDEO_OGG = ‘video/ogg‘; // do not localize
? ? ? CONTENTTYPE_VIDEO_QUICKTIME = ‘video/quicktime‘; // do not localize
? ? ? CONTENTTYPE_VIDEO_WEBM = ‘video/webm‘; // do not localize
? ? ? CONTENTTYPE_VIDEO_X_MATROSKA = ‘video/x-matroska‘; // do not localize
? ? ? CONTENTTYPE_VIDEO_X_MS_WMV = ‘video/x-ms-wmv‘; // do not localize
? ? ? CONTENTTYPE_VIDEO_X_FLV = ‘video/x-flv‘; // do not localize
? ? ? // Type Application - Vendor Specific
? ? ? CONTENTTYPE_APPLICATION_VND_OASIS_OPENDOCUMENT_TEXT = ‘application/vnd.oasis.opendocument.text‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_VND_OASIS_OPENDOCUMENT_SPREADSHEET = ‘application/vnd.oasis.opendocument.spreadsheet‘;
? ? ? // do not localize
? ? ? CONTENTTYPE_APPLICATION_VND_OASIS_OPENDOCUMENT_PRESENTATION = ‘application/vnd.oasis.opendocument.presentation‘;
? ? ? // do not localize
? ? ? CONTENTTYPE_APPLICATION_VND_OASIS_OPENDOCUMENT_GRAPHICS = ‘application/vnd.oasis.opendocument.graphics‘;
? ? ? // do not localize
? ? ? CONTENTTYPE_APPLICATION_VND_MS_EXCEL = ‘application/vnd.ms-excel‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_SPREADSHEETML_SHEET =
? ? ? ? ‘application/vnd.openxmlformats-officedocument.spreadsheetml.sheet‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_VND_MS_POWERPOINT = ‘application/vnd.ms-powerpoint‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_PRESENTATIONML_PRESENTATION =
? ? ? ? ‘application/vnd.openxmlformats-officedocument.presentationml.presentation‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_WORDPROCESSINGML_DOCUMENT =
? ? ? ? ‘application/vnd.openxmlformats-officedocument.wordprocessingml.document‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_VND_MOZILLA_XUL_XML = ‘application/vnd.mozilla.xul+xml‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_VND_GOOGLE_EARTH_KML_XML = ‘application/vnd.google-earth.kml+xml‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_VND_GOOGLE_EARTH_KMZ = ‘application/vnd.google-earth.kmz‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_VND_DART = ‘application/vnd.dart‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_VND_ANDROID_PACKAGE_ARCHIVE = ‘application/vnd.android.package-archive‘; // do not localize
? ? ? // Type X (RFC 6648)
? ? ? CONTENTTYPE_APPLICATION_X_DEB = ‘application/x-deb‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_DVI = ‘application/x-dvi‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_FONT_TTF = ‘application/x-font-ttf‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_JAVASCRIPT = ‘application/x-javascript‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_LATEX = ‘application/x-latex‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_MPEGURL = ‘application/x-mpegURL‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_RAR_COMPRESSED = ‘application/x-rar-compressed‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_SHOCKWAVE_FLASH = ‘application/x-shockwave-flash‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_STUFFIT = ‘application/x-stuffit‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_TAR = ‘application/x-tar‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_WWW_FORM_URLENCODED = ‘application/x-www-form-urlencoded‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_XPINSTALL = ‘application/x-xpinstall‘; // do not localize
? ? ? CONTENTTYPE_AUDIO_X_AAC = ‘audio/x-aac‘; // do not localize
? ? ? CONTENTTYPE_AUDIO_X_CAF = ‘audio/x-caf‘; // do not localize
? ? ? CONTENTTYPE_IMAGE_X_XCF = ‘image/x-xcf‘; // do not localize
? ? ? CONTENTTYPE_TEXT_X_GWT_RPC = ‘text/x-gwt-rpc‘; // do not localize
? ? ? CONTENTTYPE_TEXT_X_JQUERY_TMPL = ‘text/x-jquery-tmpl‘; // do not localize
? ? ? CONTENTTYPE_TEXT_X_MARKDOWN = ‘text/x-markdown‘; // do not localize
? ? ? // Type PKCS (Cryptography)
? ? ? CONTENTTYPE_APPLICATION_X_PKCS12 = ‘application/x-pkcs12‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_PKCS7_CERTIFICATES = ‘application/x-pkcs7-certificates‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_PKCS7_CERTREQRESP = ‘application/x-pkcs7-certreqresp‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_PKCS7_MIME = ‘application/x-pkcs7-mime‘; // do not localize
? ? ? CONTENTTYPE_APPLICATION_X_PKCS7_SIGNATURE = ‘application/x-pkcs7-signature‘; // do not localize
? ? ? // Type Application - Embarcadero Specific
? ? ? CONTENTTYPE_APPLICATION_VND_EMBARCADERO_FIREDAC_JSON = ‘application/vnd.embarcadero.firedac+json‘; // do not localize

? ? function ContentTypeToString(AContentType: TRESTContentType): string;
? ? function ContentTypeFromString(const AContentType: string): TRESTContentType;

? ? function IsTextualContentType(AContentType: TRESTContentType) : boolean; overload;
? ? function IsTextualContentType(const AContentType: string) : boolean; overload;
?

2.3、

TRESTRequestMethod枚举

? rmPOST
? rmPUT
? rmGET
? rmDELETE
? rmPATCH

--->

? const
? ? sRequestDefaultAccept = CONTENTTYPE_APPLICATION_JSON + ‘, ‘ +
? ? ? CONTENTTYPE_TEXT_PLAIN + ‘; q=0.9, ‘ + CONTENTTYPE_TEXT_HTML + ‘;q=0.8,‘;
? ? // UTF-8 is prefered, any other is good, but marked down:
? ? sRequestDefaultAcceptCharset = ‘utf-8, *;q=0.8‘;
? ? sDefaultFallbackCharSetEncoding = ‘utf-8‘;
? ? sDefaultUserAgent = ‘Embarcadero RESTClient/‘ + RESTCLIENT_VERSION;
? ? sBody = ‘body‘;
? ? sFile = ‘file‘;

2.4、

RESTRequest.ResetToDefaults;

? ? Method := DefaultRESTRequestMethod;
? ? Resource := ‘‘;
? ? ResourceSuffix := ‘‘;
? ? Timeout := 30000; // Some servers may be slow. Esp if they just recycled and need to start up on their first request
? ? Accept := sRequestDefaultAccept;
? ? AcceptCharset := sRequestDefaultAcceptCharset;
? ? HandleRedirects := True;
? ? FExecutionPerformance.Clear;
? ? FURLAlreadyEncoded := False;
? ? FParams.Clear;
? ? FTransientParams.Clear;
? ? FBody.ClearBody;
? ? if FClient <> nil then
? ? ? FClient.ContentType := ‘‘;
? ? if FResponse <> nil then
? ? ? FResponse.ResetToDefaults;
? ? // we intentionally do not reset "FAutoCreateParams"

? var
? ? DefaultRESTRequestMethod: TRESTRequestMethod = TRESTRequestMethod.rmGET;

? ? function RESTRequestMethodToString(const AMethod: TRESTRequestMethod): string;
?

? RESTClient.ResetToDefaults;

? ? CreateHttpClient;
? ? BaseURL := ‘‘;
? ? ProxyServer := ‘‘;
? ? ProxyPort := 0;
? ? ProxyUsername := ‘‘;
? ? ProxyPassword := ‘‘;
? ? UserAgent := sDefaultUserAgent;
? ? FallbackCharsetEncoding := sDefaultFallbackCharSetEncoding;
? ? FSynchronizedEvents := True;
? ? FRaiseExceptionOn500 := True;
? ? FAutoCreateParams := True;
? ? FParams.Clear;
? ? FTransientParams.Clear;


? RESTResponse.ResetToDefaults;

?


? RESTResponseDataSetAdapter.ResetToDefaults;

--->

?

? TRESTResponse = class(TCustomRESTResponse)
? published
? ? property Content;
? ? property ContentLength;
? ? property ContentType;
? ? property ContentEncoding;
? ? property RootElement;
? ? property BindSource;
? end;

2.5、 ? TRESTClient = class(TCustomRESTClient)
? published
? ? property Authenticator;
? ? property Accept;
? ? property AcceptCharset;
? ? property AcceptEncoding;
? ? property AllowCookies;
? ? property AutoCreateParams;
? ? property BaseURL;
? ? property ContentType;
? ? property FallbackCharsetEncoding;
? ? property Params;
? ? property HandleRedirects;
? ? property RedirectsWithGET;
? ? property SecureProtocols;
? ? property ProxyPassword;
? ? property ProxyPort;
? ? property ProxyServer;
? ? property ProxyUsername;
? ? property RaiseExceptionOn500;
? ? property SynchronizedEvents;
? ? property UserAgent;
? ? property OnHTTPProtocolError;
? ? property BindSource;
? ? property OnValidateCertificate;
? ? property OnNeedClientCertificate;
? ? property OnAuthEvent;
? end;

? ?2.6、 //以流的方式下载1个文件: Download a file

? TDownloadURL = class
? private
? ? class procedure CheckForError(const AResponse: TCustomRESTResponse); static;
? public
? ? class procedure DownloadRawBytes(const AURL: string; const AStream: TStream); static;
? end;

2.7、 TRESTRequest在执行时,如果网络异常或服务器程序未启动或服务器程序错误,异常,在处理异常方面麻烦一些,其异常类(ERequestError? :uses Rest.Types)功能比较简单!

2.8、 TRESTRequest同步执行模式:

provedure TCustomRESTRequest.Execute;

2.9、 TRESTRequest异步执行模式:

? function TCustomRESTRequest.ExecuteAsync(
? ? ACompletionHandler: TCompletionHandler = nil;?
? ? ASynchronized: boolean = True;
? ? AFreeThread: boolean = True;?
? ? ACompletionHandlerWithError: TCompletionHandlerWithError = nil
? ): TRESTExecutionThread;

?Executes a request asynchronously, i.e. run it in its own thread. There is no automatic serialization op
?property access though, which means that while the execution thread runs, properties of all involved
?TCustomRESTClient and TCustomRESTRequest instances should not be touched from other threads (including the main thread)
?Using ExecuteAsync is strongly recommended on mobile platforms. iOS (and likely Android) will
?terminate an application if it considers the main thread to be unresponsive, which would be the case if
?there is a running request which takes more than a second or two to return.
  执行异步请求,即在自己的线程中运行它。没有自动序列化op
  属性访问,这意味着在执行线程运行时,所有相关的属性
  TCustomRESTClient和TCustomRESTRequest实例不应该触及从其他线程(包括主线程)
  移动平台上使用ExecuteAsync是强烈推荐。iOS(和可能Android)
  终止应用程序如果认为主线程是反应迟钝,如果这将是如此
  有一个请求,需要超过一两秒钟返回。

?摘要说明:
?The idea behind this is that the UI runs in the main thread and mobile devices should respond to user
?interaction basically immediately. Sluggish behaviour (caused by blocking the main thread) is considered
?unacceptable on these small devices.
  背后的想法是,用户界面运行在主线程和移动设备应该响应用户
  互动基本上立即。缓慢的行为(阻塞主线程所致)
  这些小设备上不可接受。

?参数: name=ARequest
?The request to be executed 要执行的请求
?:参数结束
?参数: name=ACompletionHandler
?An anonymous method that will be run after the execution completed
execute执行完成后的1个一个匿名方法

?参数: name=ASynchronized
?Specifies if ACompletioHandler will be run in the main thread‘s (True) or execution thread‘s (False) context
如果指定了ACompletioHandler,它将运行在主线程(True),否则它在执行线程的上下文运行(False)

?参数: name=AFreeThread
?If True, then the execution thread will be freed after it completed
如果True,那么运行完成后执行线程将被释放

?参数: name=ACompletionHandlerWithError
?An anonymous method that will be run if an exception is raised during execution
在执行期间如果抛出异常,这个一个匿名方法将被执行

?返回值:
?Returns a reference to the execution thread. Should only be used if AFreeThread=False,?
?as other wise the reference may get invalid unexpectedly.
  返回对执行线程的引用。只用于参数AFreeThread = False,否则
  返回的这个引用可能会意外的无效。

2.10、应用案例:

? ///<summary>系统REST.Client单元Rest请求Web服务并返回Json数据:</summary>
? ? /// <param name="AParams">:参数:RESTRequest的请求参数名的动态数组:TArray[system.string]即:TStringDynArray: 参考:System.IOUtils下的函数的初始化及实现方法:TDirectory.DoGetFiles.</param>
? ? /// <param name="AParamsValue">:参数:RESTRequest的请求参数值的动态数组.</param>
? ? /// <param name="ABaseUrl">:参数:RESTClient的URL资源的位置:即URL的第1段:BaseUrl://:最后1个"/"可带可不带:比如:http://www.cpuofbs.com:8080/或http://www.cpuofbs.com:8080均可:
? ? ? ? ? ///但不能重复"/":http://www.cpuofbs.com:8080//是错误的.
? ? /// </param>
? ? /// <param name="AResource">:参数:RESTRequest的服务器端方法函数(函数名及其参数名列表):即URL的第2段:Resource,比如:‘getRecCountOnContitions/{pWhereGroupHavingEtc}/{pDataObject}‘
? ? ? ? ? ///前缀"/"可带可不带:比如:getRecCountOnContitions/{pWhereGroupHavingEtc}/{pDataObject}
? ? ? ? ? ? ///或/getRecCountOnContitions/{pWhereGroupHavingEtc}/{pDataObject}‘均可:前缀"/"可重复.
? ? ? ? ? ///每个参数名需要用{}括起来; 多个参数名用"/"分割开来。
? ? ? ? ? ///若用浏览器地址显式的rmGET数据,使用参数的数值而非参数名,表达为比如:http://www.cpuofbs.com:8080/datasnap/rest/TServerMethods1/getRecCountOnContitions/where (1=1)/PosBill
? ? /// </param>
? ? /// <param name="AMethod">:参数:RESTRequest的请求服务器端资源的类型(方法):uses REST.Types:rmPOST发送对象到服务器 rmPUT更新已存在或发送新的服务器对象
? ? ? ? ? ///rmGET检索并取回服务器对象 rmDELETE删除服务器已寻在对象 rmPATCH打补丁更新服务器上的Jsonpairs.
? ? /// </param>
? ? /// <param name="ModeAsyncOrSync">:参数:RESTRequest的请求执行的同步或异步模式:
? ? ? ? ? ///:=Async异步模式(默认);=sync同步模式
? ? /// </param>
? ? /// <param name="ADialogService">:参数:为主线程传入1个对话框服务提供主线程调用:
? ? ? ? ? ///:=(默认nil)
? ? /// </param>
? ? /// <returns>:返回值:RESTRequest服务器端的方法返回的JSonValue:</returns>
? function RestWebService(
? ? var AParams:TArray<system.string>;//:即:TStringDynArray: 参考:System.IOUtils下的函数的初始化及实现方法:TDirectory.DoGetFiles
? ? var AParamsValue:TArray<system.string>;
? ? const ABaseUrl:string=‘‘;
? ? ? ? ? AResource:string=‘‘;
? ? ? ? ? AMethod:TRESTRequestMethod=rmGET;
? ? const ModeAsyncOrSync:string=‘Async‘;
? ? const ADialogService:TDialogService=nil
? ? ):string;//:返回的JSon作为String后需要解析

implemention

? ? function RestWebService(
? ? ? var AParams:TArray<system.string>;//:即:TStringDynArray: 参考:System.IOUtils下的函数的初始化及实现方法:TDirectory.DoGetFiles
? ? ? var AParamsValue:TArray<system.string>;
? ? ? const ABaseUrl:string=‘‘;
? ? ? ? ? ? AResource:string=‘‘;
? ? ? ? ? ? AMethod:TRESTRequestMethod=rmGET;
? ? ? const ModeAsyncOrSync:string=‘Async‘;
? ? ? const ADialogService:TDialogService=nil
? ? ):string;//:返回的JSon作为String后需要解析
? ? var
? ? ? LRESTClient: TRESTClient;
? ? ? LRESTRequest: TRESTRequest;
? ? ? LRESTResponse: TRESTResponse;
? ? ? LParamsCount:Integer;
? ? ? LEncoding:TEncoding;
? ? ? LResultStr:string;
? ? ? LTWaitResult:Cardinal;
? ? ? LThread:TThread;
? ? ? LRestReqErr:ERequestError; ?//:异常类:uses Rest.Types
? ? ? LRestReqStatusCode:Integer; //:异常响应状态码:默认0:正常值200
? ? ? LRestReqStatusText:string; ?//:异常响应状态文本:默认‘‘
? ? begin
? ? ? //1、判断参数的完整性和一致性:
? ? ? if (ABaseUrl.Trim=‘‘)
? ? ? ? or (AResource.Trim=‘‘)
? ? ? ? or (Length(AParams)<>Length(AParamsValue))
? ? ? ? or ( ?(UpperCase(ModeAsyncOrSync)<>‘ASYNC‘)
? ? ? ? ? and (UpperCase(ModeAsyncOrSync)<>‘SYNC‘) ?) then
? ? ? begin
? ? ? ? Result:=‘‘;
? ? ? ? Exit;
? ? ? end;
? ? ? //2、设置Rest组件参数:
? ? ? LRESTClient:= TRESTClient.Create(nil);
? ? ? LRESTClient.ResetToDefaults;
? ? ? LRESTClient.BaseURL:=ABaseUrl;//:重要 :设置服务器方法的资源位置
? ? ? LRESTResponse:= TRESTResponse.Create(nil);
? ? ? LRESTResponse.ResetToDefaults;
? ? ? //LRESTResponse.ContentType:=‘application/json‘;
? ? ? LRESTRequest:= TRESTRequest.Create(nil);
? ? ? LRESTRequest.ResetToDefaults;
? ? ? LRESTRequest.Client:=LRESTClient;
? ? ? LRESTRequest.Method:=AMethod;
? ? ? //LRESTRequest.SynchronizedEvents:=false;//:不要同步事件
? ? ? LRESTRequest.Resource:=AResource;//:重要:设置请求RESTRequest的服务器方法资源:方法函数名
? ? ? LRESTRequest.Response:=LRESTResponse;
? ? ? if Length(AParams)>0 then //:如果有参数
? ? ? begin
? ? ? ? LRESTRequest.Params.Clear;
? ? ? ? LEncoding:=TEncoding.GetEncoding(‘UTF8‘);
? ? ? ? for LParamsCount := 0 to Length(AParams)-1 do
? ? ? ? begin //重要:设置请求RESTRequest的参数(如果有的话):
? ? ? ? ? AParams[LParamsCount]:=LEncoding.GetString(LEncoding.GetBytes(AParams[LParamsCount]));
? ? ? ? ? AParamsValue[LParamsCount]:=LEncoding.GetString(LEncoding.GetBytes(AParamsValue[LParamsCount]));
? ? ? ? ? ? //:2.1、请求方法Method为POST时:TRESTRequestMethod.rmPOST
? ? ? ? ? ? ? //:若参数及其参数值含中文
? ? ? ? ? ? ? //:应当将参数及其参数值TEncoding.UTF8:
? ? ? ? ? ? //:或:
? ? ? ? ? ? //AParams[LParamsCount]:=TIdURI.ParamsEncode(AParams[LParamsCount], IndyTextEncoding_UTF8);
? ? ? ? ? ? ? //:TIdURI: uses IdURI ;IndyTextEncoding_UTF8: uses IdGlobal
? ? ? ? ? ? //:2.2、请求参数数值应与被调用的服务器函数的参数类型相一致:
? ? ? ? ? ? ? //:为简便易用,服务器函数的参数约定均设置成string:
? ? ? ? ? ? ? //:便于处理TDatetime和Boolean数据类型
? ? ? ? ? LRESTRequest.AddParameter(
? ? ? ? ? ? AParams[LParamsCount],
? ? ? ? ? ? AParamsValue[LParamsCount],
? ? ? ? ? ? pkURLSEGMENT);
? ? ? ? end;
? ? ? end;
? ? ? //3、执行Rest请求RESTRequest并返回响应结果RESTResponse:
? ? ? //异步执行案例:
? ? ? if UpperCase(ModeAsyncOrSync)=‘ASYNC‘ then
? ? ? begin
? ? ? ? LThread:=(
? ? ? ? LRESTRequest.ExecuteAsync(
? ? ? ? ? procedure
? ? ? ? ? begin
? ? ? ? ? ? LResultStr:=LRESTResponse.Content;
? ? ? ? ? ? //产生请求异常的响应结果:
? ? ? ? ? ? LRestReqStatusCode:=200; //:正确的返回
? ? ? ? ? ? LRestReqStatusText:=‘OK‘;//:正确的返回
? ? ? ? ? ? LRestReqErr:=ERequestError.Create(LRestReqStatusCode,LRestReqStatusText,LResultStr);
? ? ? ? ? end,
? ? ? ? ? true,
? ? ? ? ? false, //:释放执行线程
? ? ? ? ? procedure (ExceptionObject:TObject) ?//Sender:TObject
? ? ? ? ? begin ?//异常:
? ? ? ? ? ? ? if LRestReqStatusCode<>200 then //:如果请求返回异常的响应状态码
? ? ? ? ? ? ? if ExceptionObject is Exception then
? ? ? ? ? ? ? LResultStr:=‘{"result":[‘+IntToStr(LRestReqStatusCode)+‘]}‘;
? ? ? ? ? ? ? //代表:‘请求的资源或参数错误‘导致不返回任何结果;
? ? ? ? ? ? ? ?? //LResultStr:=‘{"result":[0]}‘;//代表:‘请求的资源或参数错误‘导致不返回任何结果;
? ? ? ? ? ? ? ?? //Application.ProcessMessages;
? ? ? ? ? ? ? ? ?//raise Exception.Create(‘请求的资源或参数错误‘);
? ? ? ? ? ? ? ? ?//:异常捕获类:ERESTException:Exception:uses REST.Types
? ? ? ? ? ? ? ?? //:常规方法:捕获不了异常,只能通过上述ERESTException.StatusCode传给
? ? ? ? ? ? ? ?? //:LResultStr传递的返回值给客户端主线程来提示
? ? ? ? ? end
? ? ? ? ) as TThread);
? ? ? ? LTWaitResult:=LThread.WaitFor; ?//TWaitResult
? ? ? ? if LTWaitResult=0 then
? ? ? ? begin
? ? ? ? ? Result:=LResultStr;//:返回Json格式字符串
? ? ? ? ? //4、释放Rest组件:
? ? ? ? ? LRESTClient.Free;
? ? ? ? ? LRESTRequest.Free;
? ? ? ? ? LRESTResponse.Free;
? ? ? ? ? LEncoding.Free;
? ? ? ? ? LThread.Free;
? ? ? ? end else
? ? ? ? begin
? ? ? ? ? {
? ? ? ? ? Application.ProcessMessages;
? ? ? ? ? raise Exception.Create(‘请求的资源或参数错误‘);
? ? ? ? ? ? //:异常捕获不了,只能通过返回值给客户端主线程来提示
? ? ? ? ? ? //:故而此段代码无意义!
? ? ? ? ? Result:=LResultStr;//:返回Json格式字符串
? ? ? ? ? //4、释放Rest组件:
? ? ? ? ? LRESTClient.Free;
? ? ? ? ? LRESTRequest.Free;
? ? ? ? ? LRESTResponse.Free;
? ? ? ? ? LEncoding.Free;
? ? ? ? ? LThread.Free;
? ? ? ? ? }
? ? ? ? end;
? ? ? end else
? ? ? if UpperCase(ModeAsyncOrSync)=‘SYNC‘ then
? ? ? begin //同步执行:
? ? ? ? try
? ? ? ? ? try
? ? ? ? ? ? LRESTRequest.Execute;
? ? ? ? ? ? LResultStr:=LRESTResponse.Content;
? ? ? ? ? ? //产生请求异常的响应结果:
? ? ? ? ? ? LRestReqStatusCode:=200; //:正确的返回
? ? ? ? ? ? LRestReqStatusText:=‘OK‘;//:正确的返回
? ? ? ? ? ? LRestReqErr:=ERequestError.Create(LRestReqStatusCode,LRestReqStatusText,LResultStr);
? ? ? ? ? except
? ? ? ? ? ? ? if LRestReqStatusCode<>200 then //:如果请求返回异常的响应状态码
? ? ? ? ? ? ? if ExceptionObject is Exception then
? ? ? ? ? ? ? LResultStr:=‘{"result":[‘+IntToStr(LRestReqStatusCode)+‘]}‘;
? ? ? ? ? ? ? //代表:‘请求的资源或参数错误‘导致不返回任何结果;
? ? ? ? ? ? ? ?? //LResultStr:=‘{"result":[0]}‘;//代表:‘请求的资源或参数错误‘导致不返回任何结果;
? ? ? ? ? ? ? ?? //Application.ProcessMessages;
? ? ? ? ? ? ? ? ?//raise Exception.Create(‘请求的资源或参数错误‘);
? ? ? ? ? ? ? ? ?//:异常捕获类:ERESTException:Exception:uses REST.Types
? ? ? ? ? ? ? ?? //:常规方法:捕获不了异常,只能通过上述ERESTException.StatusCode传给
? ? ? ? ? ? ? ?? //:LResultStr传递的返回值给客户端主线程来提示
? ? ? ? ? end;
? ? ? ? finally
? ? ? ? ? Result:=LResultStr;//:返回Json格式字符串
? ? ? ? ? //4、释放Rest组件:
? ? ? ? ? LRESTClient.Free;
? ? ? ? ? LRESTRequest.Free;
? ? ? ? ? LRESTResponse.Free;
? ? ? ? ? LEncoding.Free;
? ? ? ? ? LRestReqErr.Free;
? ? ? ? end;

? ? ? end;
? ? ? //其它说明:
? ? ? //REST.Client控件从服务器Rest获得数据集到客户端适配数据集:
? ? ? //LRESTResponseDataSetAdapter.Response:= LRESTResponse;
? ? ? //LRESTResponseDataSetAdapter.Dataset:= LFDMemTable;

? ? end;

2.11、调用方法:

? ? procedure TfmxRestAndRestJson.Label5Click(Sender: TObject);
? ? //Rest记录数: https://www.cpuofbs.com:8080/datasnap/rest/TServerMethods1/getRecCountOnContitions/PosBill/where (1=1)
? ? var
? ? ? LResponseContent:string;
? ? ? LRecordCount:Integer;
? ? ? LJO:TJsonObject;
? ? ? AParams:TArray<system.string>;//:即:TStringDynArray;
? ? ? AParamsValue:TStringDynArray;
? ? begin
? ? ? TabControl1.ActiveTab:=TabItem1;
? ? ? LRecordCount:=0;
? ? ? ? //TArray<system.string>动态数组初始化的方法:
? ? ? AParams := nil; ?AParamsValue := nil;
? ? ? SetLength(AParams,2);
? ? ? SetLength(AParamsValue,2);
? ? ? ? //:动态数组不设置长度进行赋值会报错:
? ? ? AParams[0]:=‘ATableOrViewName‘;
? ? ? AParams[1]:=‘ASqlWhereEtc‘;
? ? ? AParamsValue[0]:=‘PosBill‘;
? ? ? AParamsValue[1]:=‘where (1=1)‘;//‘where (corp_name=‘‘张尚书_厂部‘‘)‘;
? ? ? try
? ? ? ? try
? ? ? ? ? LResponseContent:=
? ? ? ? ? ? RestWebService(
? ? ? ? ? ? ? AParams,
? ? ? ? ? ? ? AParamsValue,
? ? ? ? ? ? ? ‘https://www.cpuofbs.com:8080/datasnap/rest/TServerMethods1/‘,
? ? ? ? ? ? ? ? //:最后"/"个/可带可不带
? ? ? ? ? ? ? ‘/getRecCountOnContitions/{ATableOrViewName}/{ASqlWhereEtc}‘,
? ? ? ? ? ? ? ? //:前缀"/"可带可不带
? ? ? ? ? ? ? TRESTRequestMethod.rmGET,
? ? ? ? ? ? ? ? //:请求方式TRESTRequestMethod不同于请求参数的种类:
? ? ? ? ? ? ? ? //TRESTRequestParameterKind.pkGETorPOST TRESTRequestParameterKind.pkURLSEGMENT
? ? ? ? ? ? ? ‘sync‘
? ? ? ? ? ? ); //:uses myFuc_Client;
? ? ? ? except
? ? ? ? ? AParams := nil; ?AParamsValue := nil;
? ? ? ? ? raise Exception.Create(‘请求的资源或参数错误‘);
? ? ? ? end;
? ? ? finally
? ? ? ? //:对上述返回udeRESTResponse.Content解析:
? ? ? ? LJO:=(TJsonObject.ParseJSONValue(LResponseContent) as TJsonObject);
? ? ? ? try
? ? ? ? ? LRecordCount:=(( LJO.GetValue(‘result‘) as TJsonArray).Items[0] as TJsonNumber).AsInt;
? ? ? ? finally
? ? ? ? ? LJO.Free;
? ? ? ? end;
? ? ? ? Memo1.Lines.Clear;
? ? ? ? Memo1.Lines.BeginUpdate;
? ? ? ? Memo1.Lines.Add(‘Rest响应内容:‘+LResponseContent);
? ? ? ? Memo1.Lines.Add(‘记录数:‘+IntToStr(LRecordCount));
? ? ? ? Memo1.Lines.EndUpdate;
? ? ? end;
? ? end;

执行结果:

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

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

?

若服务未启动或网络异常:

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

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

三、Indy技术体系: IdHTTP;?IdFTP;? IdSSLOpenSSL;? ?IdCookieManager;???IdCompressorZLib;??IdInterceptThrottler;???IdInterceptSimLog;??

非DX原生的:来源于第三方Indy

依赖:组件及其提供方的OEM开发工具的版本。依赖于不同操作系统下的库文件(libeay32、ssleay32;libeay64、ssleay64;libssl.so、libcrypto.so;libssl.a、libcrypto.a)的更新:WIndows 下的.dll动态文件,Android下的.so文件,IOS下.a静态库文件,而且还需要分区32位及64位操作系统下不同的库文件

适用于:1、服务器端Https服务的第三方SSL证书的导入和验证,2、服务器端的SSL客制化证书的生成和签发

弱势:跨平台客户端的SSL验证和Https访问,可以用,但需分平台且受制组件的版本,分发(发布)时较麻烦而已!?

优势:资格最老的网络组件提供商,协议层很强大(是delphi Datasnap (Rest)Server的Web.HTTPApp(协议)、Web.WebReq(web请求)、Web.WebBroker(web代理)的桥接底层,其它不依赖它);网络方面技术面面俱到,类库庞大,一直为delphi内置组件库

? ? IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;? //: 处理https(协议层)的OpenSSL的方式
? ? IdInterceptThrottler1: TIdInterceptThrottler;
? ? IdInterceptSimLog1: TIdInterceptSimLog;
? ? IdCookieManager1: TIdCookieManager;
? ? IdCompressorZLib1: TIdCompressorZLib;??//: 处理压缩解压

C:\Program Files (x86)\Embarcadero\Studio\20.0\source\Indy10\Protocols

案例1:??D:\delphiXEDev\HttpUpLoadAndDownLoad\IdHttpDownLoad

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

案例2:??D:\delphiXEDev\OpenSSL\OpenSSL-delphi编程Https\delphi编程HttpsDownload\Win64\Debug

网页数据抓取(抓包、网页爬取、爬虫):?

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

?

四、浏览器客户端技术JavaScript+jQuery(Mobile)+Http DOM+Ajax

非常强大,目前主流技术!

跨平台、跨操作系统、跨语言

4.1、篇幅所限,不再赘述!学习的话,可参考:

(以下转,感谢博主!)

最权威:官方产品经理:Marco Cantù的 《REST Servers in Delphi XE Using DataSnap》,网上的中文翻译版.pdf :

https://download.csdn.net/download/weixin_42404994/10742572

《REST Servers in Delphi XE Using DataSnap》源码下载:REST Servers in Delphi XE Using DataSnap.CodeSample.rar

https://download.csdn.net/download/chunyangsuhao/11429142

Delphi 10.3 Web应用开发B/S框架介绍(一):uniGUI:

https://blog.csdn.net/xyzhan/article/details/86527802

Delphi 10.3 Web应用开发B/S框架介绍(二):IntraWeb 17:

https://blog.csdn.net/xyzhan/article/details/86528302

Bootstrap中文版(响应式):

https://www.bootcss.com/

Bootstrap+H5+Css3+js网页前端可视化布局在线生成工具:

https://www.bootcss.com/p/layoutit/

w3school:Web前端技术学习大全:

https://www.w3school.com.cn/index.html? 其中内容如下:

? ? HTML及H5+CSS3教程 + 浏览器脚本 + 服务器脚本 + XML教程
? ? 其中,浏览器脚本:
? ? JavaScript、HTML DOM、jQuery、jQuery Mobile、AJAX、JSON、DHTML、E4X、WMLScript

4.2、附:delphi App中调用JavaScript方法,供学习参考::

(以下转,感谢博主!)

基于HTML模板和JSON数据的JavaScript交互:

https://blog.csdn.net/u013558749/article/details/52445049

REST Datasnap服务端与javascript客户端实现:

https://blog.csdn.net/a00553344/article/details/51719643

delphi与javascript交互:

https://download.csdn.net/download/qq_30347073/9162031

解决Delphi(FireMonkey)Andorid,IOS移动应用WebBrowser与JavaScript交互问题:

http://blog.sina.com.cn/s/blog_72eb56aa0102xkgg.html

Firemonkey扩展增强:Android 浏览器执行JavaScript获取结果及JavaScript调用本地方法:

https://blog.csdn.net/tht2009/article/details/53996177

Windows下:

Delphi 中调用JS文件中的方法:

https://www.cnblogs.com/limingliyu/p/5658767.html

delphi中执行javascript代码:

http://www.delphitop.com/html/wenjian/2780.html

4.3、其它:

JS清除缓存的几种方法:

https://blog.csdn.net/weixin_42983021/article/details/92833944

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

上一篇:加密与解密学习笔记2-windows API函数


下一篇:win10 wifi功能消失消失不见的解决办法