2021-02-18

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

摘要:


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

 

 

一、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;

既可直接使用组件

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

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

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

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

第三方案例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;


*用delphi XE开发工具NetHTTP技术体系快速入手HTTPs编程所需掌握的知识

重要参数得搞清楚:

1、请求参数:
System.Net.HttpClient.THTTPRequest

2、响应参数:
System.Net.HttpClient.IHTTPResponse  = interface(IURLResponse)  
System.Net.URLClient. IURLResponse = interface(IInterface)

 

二、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访问令牌方式或代码方式

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

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

官方案例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

或者:

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;

执行结果:

 

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

三、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

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

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

 

四、浏览器客户端技术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

菜鸟教程:

https://www.runoob.com/

H5 WebSocket:

https://www.runoob.com/html/html5-websocket.html

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

4.4、特别补充网友文章:

    4.4.1、《JavaScript中发出HTTP请求最常用的方法》https://www.jb51.net/article/143683.htm

    4.4.2、《js的http请求中请求头和响应头包含哪些内容》https://blog.csdn.net/weixin_37861326/article/details/82216068

    4.4.3、《JavaScript高级程序设计--在HTML中使用JavaScripthttps://blog.csdn.net/weixin_37861326/article/details/80998668

本博客相关:

5.1、delphi XE应用Restful时Rest组件的delphi XE ContentType即delphi XE mime type怎样获取和表达
https://blog.csdn.net/pulledup/article/details/105749158
5.2、delphi XE Restful:RestClien案例RESTDebugger.dproj和RESTDemos.dproj的调用参数及格式设置  https://blog.csdn.net/pulledup/article/detail
s/104242744

5.3、delphi MimeType for Restful及delphi mime-type和文件扩展名对照表
https://blog.csdn.net/pulledup/article/details/105774767
5.4、delphi XE基于SSL的HTTPS服务器应用程序的认证文件(Certificate.cer、CACertificate1.cer、PrivateKey.key及OnGetPassword)的配置
https://blog.csdn.net/pulledup/article/details/105408763
5.5、ssl证书绑定端口
https://blog.csdn.net/pulledup/article/details/107026471
https://download.csdn.net/download/pulledup/12409057

5.6、《Delphi调用微信原生Web开发接口JS-SDK开发小程序及微信支付等
https://blog.csdn.net/pulledup/article/details/109257077

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值