web api路由
web api路由
实现原理
web api通过资源来进行分类,一个资源可以有许多action(动作),每一个action都有一个对应web api。
对于CRUD操作,资源可以是一个数据表的映射,但不必与数据表同名。
所有的资源url必须是唯一的,一个资源url对应一个web api,通过资源url就可以调用到对应的web api。
通过唯一的资源url来定位一个web api,资源url就是key(关键字),web api就是value(值),从而形成资源url-web api对字典。将所有的web api都添加进路由字典。
查路由字典的时候,通过客户端请求的资源url这个key(关键字),就能查到对应的web api。
资源url示例
https://api.example.com/v1/user/select
1.web api方法指针类型
{$IFDEF mormot2} THttpRequest = THttpServerRequestAbstract; THttpResponse = THttpServerRequestAbstract; {$ENDIF} {$IFDEF crosssocket} THttpRequest = ICrossHttpRequest; THttpResponse = ICrossHttpResponse; {$ENDIF} TProcessRequest = procedure(const ARequest: THttpRequest; const AResponse: THttpResponse) of object;
2.web api路由
unit core.router; //cxg 2025 interface uses core.global, core.json, Generics.Collections, SysUtils; type TRouter = record class var Dict: TDictionary<string, TProcessRequest>; //路由字典 资源url-api对 class procedure Route(const ARequest: THttpRequest;//字典查路由 const AResponse: THttpResponse); static; class procedure Add(const APath: string;//往字典添加路由 const OnRequest: TProcessRequest); static; end; implementation class procedure TRouter.Route(const ARequest: THttpRequest; const AResponse: THttpResponse); var LPath: string; LResponseData: TJsonO; LSuccess: bool; begin LSuccess := False; for LPath in TRouter.Dict.Keys do begin if LPath = TRequestFunc.Path(ARequest) then//字典查到了 begin LSuccess := true; TRouter.Dict[LPath](ARequest, AResponse); Exit; end; end; if not LSuccess then//字典没有查到 begin LResponseData := TJsonO.Create; LResponseData.B['success'] := False; LResponseData.S['message'] := 'Route fail.'; TResponseFunc.Send(AResponse, LResponseData); end; end; class procedure TRouter.Add(const APath: string; const OnRequest: TProcessRequest); begin if not assigned(TRouter.Dict) then TRouter.Dict := TDictionary<string, TProcessRequest>.Create; TRouter.Dict.Add(APath, OnRequest); end; end.
3.web api实现
type TFormData = record procedure DownloadFile(const ARequest: THttpRequest; const AResponse: THttpResponse); procedure UploadFile(const ARequest: THttpRequest; const AResponse: THttpResponse); procedure Select(const ARequest: THttpRequest; const AResponse: THttpResponse); end;
4.web api添加路由字典
var FormData: TFormData; //资源url和web api一 一 对应,组成队 initialization TRouter.Add('/formdata/downloadfile', FormData.DownloadFile); TRouter.Add('/formdata/uploadfile', FormData.UploadFile); TRouter.Add('/formdata/select', FormData.Select);
5.客户端请求服务演示
客户端web api定义
TRpc = record //CRUD class function Select(const ADbid: string; ASqls: TArray<string>; ADataSets: TArray<TDataSet>): boolean; static; class function Insert(const ADbid: string; ATableNames: TArray<string>; ANonSaveFields: TArray<string>; ADataSets: TArray<TDataSet>; ACurrentRecordOnly: boolean): boolean; static; class function Update(const ADbid: string; ATableNames: TArray<string>; ANonSaveFields: TArray<string>; ADataSets: TArray<TDataSet>; ACurrentRecordOnly: boolean): boolean; static; class function Delete(const ADbid: string; ATableNames: TArray<string>; ADataSets: TArray<TDataSet>; ACurrentRecordOnly: boolean) : boolean; static; class function Save(const ADbid: string; ATableNames: TArray<string>; ANonSaveFields: TArray<string>; ADataSets: TArray<TDataSet>; AState: TDataSetState; ACurrentRecordOnly: boolean): boolean; static; class function StoredProc(ARequestData: TJsonO): TJsonO; static; //file transfer class function DownloadFile(const AFileName: string): TJsonO; static; class function UploadFile(const ARequestData: TJsonO): boolean; static; end;
客户端请求服务
客户端请求服务的参数统一使用json格式的数据。服务端应答数据也统一使用json格式的数据。
凡一切有http client的工具开发的客户端都支持。
class function TRpc.Select(const ADbid: string; ASqls: TArray<string>; ADataSets: TArray<TDataSet>): boolean; var LHttp: THttpClient; LRequestData, LResponseData: TJsonO; LRequestStream, LResponseStream: TStream; i: integer; begin if ADbid = '' then Exit; LHttp := NewHttp; LRequestData := TJsonO.Create; LResponseStream := TMemoryStream.Create; try LRequestData.S['dbid'] := ADbid;//请求参数统一使用json数据 LRequestData.i['count'] := High(ASqls) + 1; for i := 0 to High(ASqls) do LRequestData.S['sql' + i.ToString] := ASqls[i]; LRequestStream := LRequestData.ToStream;//请求参数json数据转换为流 LHttp.Post(url + '/webapi/select', LRequestStream, LResponseStream);//http post 发送请求 LResponseData := SO(LResponseStream);//应答数据还原为json Result := LResponseData.B['success']; if Result then begin for i := 0 to High(ASqls) do begin ADataSets[i].JsonArrayToFields(LResponseData.A['fields' + i.ToString]); ADataSets[i].JsonArrayToData(LResponseData.A['data' + i.ToString]); end; end; finally LRequestStream.Free; LResponseStream.Free; LHttp.Free; LRequestData.Free; LResponseData.Free; end; end;
本文来自博客园,作者:{咏南中间件},转载请注明原文链接:https://www.cnblogs.com/hnxxcxg/p/19072786