體為 REST API)
簡(jiǎn)介面向Delphi 12.3開(kāi)發(fā)者的TMS XData v5.21.0.0控件包是一套基于REST架構(gòu)的數(shù)據(jù)訪問(wèn)框架用于快速構(gòu)建可提供增刪改查接口的服務(wù)端應(yīng)用解決網(wǎng)絡(luò)服務(wù)開(kāi)發(fā)中架構(gòu)選型與組件集成的常見(jiàn)痛點(diǎn)。壓縮包為7z格式體積僅3.2MB共582個(gè)文件包含249個(gè)pas源代碼、33個(gè)dpr工程文件和29個(gè)dpk包文件用于編譯安裝76個(gè)dfm窗體布局文件37個(gè)html說(shuō)明頁(yè)面及chm編譯幫助另有css/js等前端資源與少量pdf/txt說(shuō)明。整體并非僅僅是庫(kù)文件而是完整的組件工程與文檔集合。目前已有67人學(xué)習(xí)下載對(duì)于正在選型或準(zhǔn)備上手TMS XData的Delphi開(kāi)發(fā)者具有直接參考價(jià)值。通過(guò)249個(gè)pas源碼可深入理解組件內(nèi)部實(shí)現(xiàn)借助dpr/dpk示例工程和chm幫助手冊(cè)能快速建立RESTful服務(wù)支持JSON/XML數(shù)據(jù)交換包內(nèi)html/css/js等Web資源可用于前端聯(lián)調(diào)配合dfm窗體布局文件可降低界面與接口的對(duì)接成本。無(wú)論初學(xué)者還是資深Delphi程序員都能減少底層網(wǎng)絡(luò)通信的重復(fù)勞動(dòng)更專注于業(yè)務(wù)邏輯顯著縮短數(shù)據(jù)服務(wù)開(kāi)發(fā)周期。1. TMS XData v5.21.0.0在 Delphi 12.3 里讓業(yè)務(wù)模型直接長(zhǎng)出 REST API 的控件做 Delphi 后端的人應(yīng)該都碰過(guò)這種局面Aurelius 實(shí)體已經(jīng)寫(xiě)好了數(shù)據(jù)庫(kù)表也定完了但前端要調(diào)一個(gè)GET /customers還得單獨(dú)搭一套 HTTP 服務(wù)寫(xiě)路由、寫(xiě) JSON 序列化、寫(xiě)鑒權(quán)折騰半天。TMS XData v5.21.0.0 就是專門解決這個(gè)重復(fù)勞動(dòng)的控件集它基于 Delphi 12.3 編譯鏈直接把 Aurelius ORM 實(shí)體暴露成標(biāo)準(zhǔn) REST/JSON 資源自動(dòng)生成 CRUD 端點(diǎn)順帶把 JWT 鑒權(quán)、CORS、日志這些服務(wù)端基礎(chǔ)設(shè)施也放進(jìn)組件里。適合已經(jīng)用 Delphi 做業(yè)務(wù)系統(tǒng)、需要把數(shù)據(jù)開(kāi)放給 Web/H5/移動(dòng)端復(fù)用的團(tuán)隊(duì)也適合想在不換技術(shù)棧的前提下做輕量中臺(tái)的場(chǎng)景。2. 環(huán)境與安裝先讓 Delphi 12.3 認(rèn)識(shí) TMS XData v5.21.0.02.1 版本匹配為什么是 v5.21.0.0 而不是手寫(xiě) HTTP 服務(wù)先說(shuō)結(jié)論TMS XData v5.21.0.0 這份資源是按 Delphi 12.3 Athens 編譯的項(xiàng)目的源碼路徑、BPL 包名、設(shè)計(jì)期注冊(cè)邏輯都對(duì)齊了這一代 IDE。如果你還在用 Delphi 10.3 或 11直接裝大概率會(huì)報(bào)DCU版本不匹配或者找不到System.Net的某個(gè)類型這不是資源有問(wèn)題而是編譯工具鏈不匹配后面避坑部分會(huì)詳細(xì)說(shuō)。那為什么不手寫(xiě)一個(gè) WebBroker 服務(wù)我早年也這么干過(guò)在TWebModule里自己解析Request.PathInfo、手寫(xiě)Response.Content再處理 URL 編碼和日期格式。短期內(nèi)接口少還能扛一旦實(shí)體超過(guò)十個(gè)每個(gè)實(shí)體都要寫(xiě) CRUD 路由、參數(shù)校驗(yàn)、分頁(yè)、排序代碼量翻著倍走而且所有接口的 JSON 格式靠人肉保證前端稍微挑點(diǎn)格式問(wèn)題就得來(lái)回返工。XData 在這個(gè)場(chǎng)景下更像一個(gè)資源映射器實(shí)體類就是 API 資源屬性就是字段路由、序列化、HTTP 方法映射全部自動(dòng)完成。2.2 安裝步驟解壓、加庫(kù)路徑、編譯安裝拿到的是 .7z 壓縮包不是 installer所以安裝要做幾步手工操作但每一步都可控。先把壓縮包釋放到一個(gè)不帶空格的目錄我的習(xí)慣是放D:\Libs\tms\xdata_521不建議丟到系統(tǒng)盤(pán)或者帶中文名的路徑Delphi 的庫(kù)路徑對(duì)中文路徑支持一直不太穩(wěn)定。接下來(lái)打開(kāi) Delphi 12.3做三件事步驟操作說(shuō)明1Tools Options Environment Variables里新增變量變量名TMS_XDATA指向解壓根目錄后續(xù)庫(kù)路徑可以直接引用2Tools Options Delphi Options Library Library Path追加源碼路徑把$(TMS_XDATA)\source或?qū)?yīng)版本目錄加進(jìn)去讓 IDE 能索引到單元文件3打開(kāi)包工程組并順序編譯在packages目錄下找到 Delphi 12 對(duì)應(yīng)的.groupproj先編譯運(yùn)行時(shí)包.dpk再編譯設(shè)計(jì)期包并右鍵Install注意第三步的順序很關(guān)鍵XData 的運(yùn)行時(shí)包依賴 Aurelius 的運(yùn)行時(shí)包如果直接把設(shè)計(jì)期包拿去 Install會(huì)因?yàn)檎也坏降讓?DCU 報(bào)錯(cuò)。正確順序是從下往上編譯先Aurelius再XData核心最后才是設(shè)計(jì)期注冊(cè)包??吹紻esign package installed的提示并且 Tool Palette 里出現(xiàn)TMS XData分類就說(shuō)明裝上了。2.3 驗(yàn)證安裝用自帶 Demo 建立第一個(gè)服務(wù)器XData 安裝包通常會(huì)帶示例工程路徑一般在demos或samples目錄下。優(yōu)先找名字帶WebModule或者Server的示例打開(kāi)后編譯運(yùn)行瀏覽器訪問(wèn)http://localhost:8080/tms/xdata/info如果返回一段 JSON列出 XData 版本號(hào)和服務(wù)狀態(tài)就說(shuō)明整條鏈路是通的。這里有個(gè)關(guān)鍵的驗(yàn)證點(diǎn)/tms/xdata是 XData 的默認(rèn)根路徑后面跟的info是框架自帶的服務(wù)信息接口。如果瀏覽器訪問(wèn)能看到類似product : TMS XData的字段說(shuō)明不僅是組件裝好了連接池和請(qǐng)求分發(fā)也正常。如果這一步就 404優(yōu)先查端口是不是被別的服務(wù)占了再查 WebModule 有沒(méi)有被正確加載。3. 模型先行用 Aurelius 實(shí)體把數(shù)據(jù)表變成 REST 資源3.1 數(shù)據(jù)模型即 APIXData 如何做映射XData 的核心設(shè)計(jì)理念是模型即接口它不做獨(dú)立的接口編排層而是直接讀取 Aurelius 實(shí)體的元數(shù)據(jù)。實(shí)體類上的[Entity]、屬性上的[Column]這些注解在運(yùn)行期被 XData 翻譯成資源的名稱、字段的 JSON 鍵名和類型。也就是說(shuō)你寫(xiě)實(shí)體類的時(shí)候接口文檔其實(shí)已經(jīng)同步確定了。這意味著兩件事第一字段名、類型、是否可空都會(huì)直接影響 API 表現(xiàn)設(shè)計(jì)實(shí)體類時(shí)要站在前端視角想這個(gè)字段能不能為 null、應(yīng)該返回字符串還是整數(shù)第二XData 端點(diǎn)的資源名默認(rèn)是實(shí)體類名的復(fù)數(shù)形式比如TCustomer對(duì)應(yīng)的資源路徑就是/customers如果你在代碼里寫(xiě)的是TUserInfo那路徑就是/userInfo大小寫(xiě)和復(fù)數(shù)化規(guī)則要心里有數(shù)否則前端按文檔調(diào)不到。3.2 寫(xiě)一個(gè) TCustomer 實(shí)體注解、主鍵與默認(rèn)命名下面是最小可運(yùn)行的實(shí)體定義以客戶表為例unit uCustomer; interface uses Aurelius.Mapping.Attributes; type [Entity] [Table(Customers)] TCustomer class private [Column(Id, [TColumnProp.Identity])] FId: Integer; [Column(Name, [])] FName: string; [Column(Email, [])] FEmail: string; public property Id: Integer read FId write FId; property Name: string read FName write FName; property Email: string read FEmail write FEmail; end; implementation end.這段代碼里有兩個(gè)容易忽略的參數(shù)TColumnProp.Identity表示主鍵自增XData 在生成POST /customers接口時(shí)會(huì)認(rèn)為不需要客戶端傳入 Id而PUT /customers(1)則會(huì)要求 URL 里的(1)與實(shí)體主鍵匹配。如果主鍵屬性沒(méi)標(biāo)Identity創(chuàng)建資源的接口就要求你在 JSON Body 里顯式傳主鍵行為完全不同。3.3 多表和關(guān)聯(lián)關(guān)系Master-Detail 資源怎么暴露實(shí)際業(yè)務(wù)很少只有單表XData 對(duì)關(guān)聯(lián)關(guān)系的處理是實(shí)體屬性直接引用另一個(gè)實(shí)體類JSON 序列化時(shí)會(huì)輸出嵌套對(duì)象。舉個(gè)例子訂單和客戶的關(guān)系type [Entity] [Table(Orders)] TOrder class private [Column(Id, [TColumnProp.Identity])] FId: Integer; [Column(CustomerId, [])] FCustomerId: Integer; [Column(TotalAmount, [])] FTotalAmount: Double; FCustomer: TCustomer; public property Id: Integer read FId write FId; property CustomerId: Integer read FCustomerId write FCustomerId; property TotalAmount: Double read FTotalAmount write FTotalAmount; [Association([TAssociationProp.LazyLoading])] property Customer: TCustomer read FCustomer write FCustomer; end;注意Association注解上的LazyLoading參數(shù)。我一般會(huì)默認(rèn)打開(kāi)懶加載這樣查詢訂單列表時(shí)不會(huì)把每個(gè)訂單的客戶對(duì)象都帶出來(lái)JSON 體積會(huì)小很多。前端需要客戶詳情時(shí)再單獨(dú)調(diào)/customers(2)取數(shù)據(jù)這也是 REST 接口更合理的使用方式。如果不加懶加載訂單量大時(shí)響應(yīng)會(huì)明顯變慢這是新手最容易踩的坑。4. 把 CRUD 暴露成 APIXData 端點(diǎn)、篩選參數(shù)和自定義業(yè)務(wù)方法4.1 自動(dòng) CRUD 端點(diǎn)GET/POST/PUT/DELETE 映射規(guī)則實(shí)體類編譯進(jìn)去之后XData 會(huì)自動(dòng)注冊(cè)一套標(biāo)準(zhǔn)端點(diǎn)映射關(guān)系非常直觀HTTP 方法URL 示例行為GET/customers返回客戶列表默認(rèn)分頁(yè) 100 條GET/customers(15)返回單條記錄主鍵為 15POST/customers創(chuàng)建記錄Body 放 JSON 對(duì)象PUT/customers(15)整體更新記錄 15DELETE/customers(15)刪除記錄 15這套映射不需要寫(xiě)一行路由代碼。需要留意的坑是 URL 里主鍵的括號(hào)寫(xiě)法是 OData 風(fēng)格不是常見(jiàn)的/customers/15前端如果按路徑參數(shù)的習(xí)慣拼接就會(huì) 404。我一般會(huì)在接口文檔里顯式告訴前端這個(gè)規(guī)則順手在 WebModule 的響應(yīng)頭里加上X-XData-EntitySet: customers之類的自定義頭方便排查問(wèn)題。4.2 分頁(yè)、篩選與排序$top/$skip/$filter 的實(shí)際用法XData 對(duì)列表接口默認(rèn)支持一組查詢前綴參數(shù)這是它區(qū)別于一個(gè)實(shí)體一個(gè)固定接口的另一個(gè)優(yōu)點(diǎn)??匆粋€(gè)實(shí)際請(qǐng)求GET /tms/xdata/customers?$top20$skip40$filterTotalAmount gt 1000$orderbyName desc參數(shù)含義拆開(kāi)說(shuō)$top20只取前 20 條等價(jià)于 SQL 里的LIMIT 20。$skip40跳過(guò)前 40 條和$top配合做分頁(yè)。前端常見(jiàn)的第 3 頁(yè)每頁(yè) 20 條就是$skip40$top20。$filterTotalAmount gt 1000是服務(wù)端過(guò)濾gt是大于的意思XData 會(huì)把它翻譯成 SQL 的 WHERE 條件不會(huì)出現(xiàn)查出全量再在內(nèi)存里過(guò)濾這種災(zāi)難。$orderbyName desc指定排序字段和方向多個(gè)字段用逗號(hào)分隔。這套參數(shù)是可以疊加的但要注意$filter的字段名必須和 JSON 序列化后的字段名一致。如果你在實(shí)體屬性上用了[Column(full_name)]但屬性名是FName那 URL 里應(yīng)該寫(xiě)full_name還是Name以 JSON 鍵名為準(zhǔn)這個(gè)細(xì)節(jié)在聯(lián)調(diào)前先確認(rèn)一次能省半天排查時(shí)間。4.3 自定義業(yè)務(wù)方法在服務(wù)類上開(kāi)新的路由自動(dòng) CRUD 覆蓋的是標(biāo)準(zhǔn)增刪改查但業(yè)務(wù)里總有查詢某用戶最近十筆訂單這種聚合邏輯。XData 允許在服務(wù)器端注冊(cè)服務(wù)類把方法暴露成額外端點(diǎn)。我常用的做法是在獨(dú)立的單元里定義服務(wù)接口不寫(xiě)進(jìn)實(shí)體類type TCustomerService class public function GetRecentOrders(CustomerId: Integer; Count: Integer 10): TListTOrder; end;服務(wù)器啟動(dòng)時(shí)把它注冊(cè)進(jìn) XData 的服務(wù)集合里前端就可以直接請(qǐng)求GET /tms/xdata/Service/GetRecentOrders?CustomerId5Count10這個(gè)路徑的規(guī)則是Service固定后面跟著類名和方法名參數(shù)走查詢字符串。好處是業(yè)務(wù)邏輯留在 Delphi 端可以繼續(xù)用 Aurelius 的查詢語(yǔ)法、事務(wù)和連接池不用為了一個(gè)聚合查詢?nèi)?xiě)裸 SQL。我建議自定義服務(wù)方法統(tǒng)一走這種模式而不是另開(kāi)一個(gè) HTTP 端口。4.4 客戶端調(diào)用用原生 RESTClient 做最小聯(lián)調(diào)雖然 TMS 提供了官方的 XData Client 組件但我聯(lián)調(diào)時(shí)更習(xí)慣先用 Delphi 自帶的TNetHTTPClient把接口調(diào)通少一層依賴出了問(wèn)題也好判斷是服務(wù)端還是客戶端的事uses System.Net.HttpClient, System.JSON; var HttpClient: TNetHTTPClient; Response: IHTTPResponse; JSONValue: TJSONValue; begin HttpClient : TNetHTTPClient.Create(nil); try Response : HttpClient.Get(http://localhost:8080/tms/xdata/customers?$top10); if Response.StatusCode 200 then begin JSONValue : TJSONObject.ParseJSONValue(Response.ContentAsString(TEncoding.UTF8)); try // JSONValue 里就是客戶列表數(shù)組 WriteLn(JSONValue.ToString); finally JSONValue.Free; end; end; finally HttpClient.Free; end; end;TNetHTTPClient.Get返回的IHTTPResponse里包含狀態(tài)碼、響應(yīng)頭和 Body狀態(tài)碼 200 是正常401 是鑒權(quán)失敗404 多半是資源名和實(shí)體名沒(méi)對(duì)上。這里用TJSONObject.ParseJSONValue解析響應(yīng)不引入額外的 JSON 庫(kù)聯(lián)調(diào)階段夠用了。5. 避坑與排查XData 部署中常見(jiàn)的七個(gè)翻車現(xiàn)場(chǎng)5.1 安裝后 IDE 里找不到 XData 組件面板現(xiàn)象按步驟編譯了設(shè)計(jì)期包Install 也提示成功但 Tool Palette 里搜不到TMS XData。原因有兩個(gè)一是庫(kù)路徑里源碼目錄順序不對(duì)IDE 索引到了舊版本的 DCU二是安裝了很多第三方組件組件包分類被折疊了。解決在 Tool Palette 右上角搜索框里直接輸入TXDataServer如果搜不到回到Components Install Packages里確認(rèn)設(shè)計(jì)期包名字前打了勾再把庫(kù)路徑里舊版路徑刪掉重啟 IDE。5.2 GET 請(qǐng)求返回 500服務(wù)端日志卻一片空白現(xiàn)象瀏覽器訪問(wèn)/customers返回 500 Internal Server ErrorWebModule 的 OnLog 事件什么都沒(méi)打。原因通常是實(shí)體類的屬性映射問(wèn)題比如數(shù)據(jù)庫(kù)表里沒(méi)有Name列但實(shí)體里寫(xiě)了Name這個(gè)錯(cuò)誤在 XData 生成查詢語(yǔ)句時(shí)才拋出而異常被框架吞進(jìn)了默認(rèn)日志通道。解決先在瀏覽器訪問(wèn)/tms/xdata/info確認(rèn)服務(wù)正常再直接調(diào)用/customers(1)縮小范圍最后檢查實(shí)體類映射和數(shù)據(jù)庫(kù)字段是否一一對(duì)應(yīng)。5.3 JSON 日期時(shí)間格式和前端預(yù)期不一致現(xiàn)象前端拿到的是2024-05-12T08:30:00.000Z但頁(yè)面顯示時(shí)多了 8 小時(shí)。原因Delphi 的TDateTime本身沒(méi)有時(shí)區(qū)概念XData 序列化時(shí)按服務(wù)器本地時(shí)間輸出而前端 JavaScript 的new Date()默認(rèn)按瀏覽器時(shí)區(qū)渲染。解決在服務(wù)器端統(tǒng)一定義時(shí)間基準(zhǔn)我一般會(huì)在部署文檔里約定所有接口返回 UTC 時(shí)間前端拿到后再轉(zhuǎn)當(dāng)?shù)貢r(shí)間。如果是內(nèi)部系統(tǒng)不想改邏輯就在前端解析時(shí)忽略時(shí)區(qū)字段按純字符串處理。5.4 SQLite 并發(fā)請(qǐng)求時(shí)頻繁報(bào)database is locked現(xiàn)象請(qǐng)求量稍微上來(lái)SQLite 為后端的服務(wù)就開(kāi)始間歇性 500。原因SQLite 默認(rèn)單連接串行寫(xiě)XData 的連接池在并發(fā)寫(xiě)場(chǎng)景下會(huì)同時(shí)打開(kāi)多個(gè)連接其中一個(gè)拿到鎖其他就排隊(duì)失敗。解決SQLite 適合接口量小、并發(fā)低的內(nèi)部工具如果要做多用戶在線服務(wù)把數(shù)據(jù)庫(kù)切到 MySQL/SQL Server連接字符串改一下應(yīng)用代碼不用動(dòng)。這個(gè)項(xiàng)目里如果已經(jīng)踩了 SQLite 的坑別猶豫趁早換庫(kù)。5.5 CORS 配置不生效前端跨域被瀏覽器攔截現(xiàn)象前端跑在localhost:4200后端跑在8080瀏覽器控制臺(tái)報(bào)跨域錯(cuò)誤但代碼里明明設(shè)置了Access-Control-Allow-Origin。原因CORS 的響應(yīng)頭必須要在預(yù)檢請(qǐng)求階段返回也就是OPTIONS請(qǐng)求也要有對(duì)應(yīng)處理很多人只處理了 GET/POST 而漏掉了 OPTIONS。解決在 WebModule 的 BeforeDispatch 事件里統(tǒng)一加三個(gè)響應(yīng)頭Response.SetCustomHeader(Access-Control-Allow-Origin, *); Response.SetCustomHeader(Access-Control-Allow-Methods, GET, POST, PUT, DELETE, OPTIONS); Response.SetCustomHeader(Access-Control-Allow-Headers, Authorization, Content-Type, X-XData-*);Access-Control-Allow-Headers里的Authorization是給 JWT 用的Content-Type是給 JSON 請(qǐng)求體用的。注意*在需要攜帶 Cookie 的場(chǎng)景下不適用那時(shí)要寫(xiě)具體域名。5.6 URL 資源名大小寫(xiě)導(dǎo)致 404現(xiàn)象實(shí)體類叫TUserInfo前端訪問(wèn)/userinfo是通的但訪問(wèn)/userInfo就 404。原因XData 的資源名映射保留了實(shí)體類名的原始大小寫(xiě)而且默認(rèn)復(fù)數(shù)化時(shí)不改大小寫(xiě)。解決約定所有資源名統(tǒng)一小寫(xiě)訪問(wèn)或者在實(shí)體類上用[Entity(userinfo)]顯式指定資源名不要讓前端去猜大小寫(xiě)規(guī)則。5.7 部署到 Windows 服務(wù)后模塊不加載現(xiàn)象開(kāi)發(fā)環(huán)境一切正常放到服務(wù)器上注冊(cè)成 Windows 服務(wù)一啟動(dòng)就報(bào)模塊不存在或找不到指定的模塊。原因跑 WebBroker 應(yīng)用需要依賴Delphi 12.3的運(yùn)行時(shí) DLL如rtl290.bpl等服務(wù)器上沒(méi)裝對(duì)應(yīng)版本運(yùn)行時(shí)庫(kù)。解決發(fā)布時(shí)選用Release Static編譯模式并勾選Link with runtime packages取消勾選讓 BPL 依賴打進(jìn) EXE。如果你是做綠色發(fā)布記得把XData和Aurelius注冊(cè)運(yùn)行庫(kù)包也做好靜默安裝腳本不然換臺(tái)機(jī)器就翻車。6. 收尾技巧給 XData 服務(wù)加日志、鑒權(quán)和聯(lián)調(diào)腳本6.1 用攔截器記錄每次請(qǐng)求耗時(shí)生產(chǎn)環(huán)境里最怕的就是接口偶爾慢一下但說(shuō)不出具體是哪個(gè)請(qǐng)求慢。XData 服務(wù)端的WebModule里有兩個(gè)事件可以利用BeforeDispatch和AfterDispatch。我在BeforeDispatch里記錄開(kāi)始時(shí)間在AfterDispatch里計(jì)算耗時(shí)再拼上請(qǐng)求路徑、查詢參數(shù)、狀態(tài)碼一行結(jié)構(gòu)化日志就出來(lái)了procedure TXDataWebModule.WebModuleBeforeDispatch(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean); begin FStartTick : TStopwatch.GetTimestamp; end; procedure TXDataWebModule.WebModuleAfterDispatch(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean); var ElapsedMs: Int64; begin ElapsedMs : (TStopwatch.GetTimestamp - FStartTick) * TStopwatch.TicksPerMillisecond; LogRequest(Request.PathInfo, Request.Query, Response.StatusCode, ElapsedMs); end;這一段代碼簡(jiǎn)單直接只要在LogRequest里把信息寫(xiě)進(jìn)日志文件或數(shù)據(jù)庫(kù)就足夠定位百分之八十的性能問(wèn)題。慢查詢的特征很統(tǒng)一$filter條件沒(méi)走索引、$skip頁(yè)數(shù)太大、關(guān)聯(lián)對(duì)象懶加載被逐條觸發(fā)日志里一看耗時(shí)就能確定方向。6.2 配合 FireMonkey 客戶端快速聯(lián)調(diào)XData 做服務(wù)端Delphi 12.3 的 FireMonkey 做客戶端是同一個(gè)技術(shù)棧下很舒服的組合。我一般會(huì)在客戶端工程里放一個(gè)調(diào)試窗體放一個(gè)TEdit填 URL一個(gè)TMemo看返回結(jié)果再放幾個(gè)按鈕對(duì)應(yīng) GET、POST、PUT、DELETE。聯(lián)調(diào)時(shí)不需要斷點(diǎn)直接在這個(gè)調(diào)試面板里發(fā)請(qǐng)求返回的 JSON 格式化打印出來(lái)前端同學(xué)要什么字段一眼就能對(duì)照。這個(gè)方法每次調(diào)試都幫我篩掉一類問(wèn)題到底是接口數(shù)據(jù)不對(duì)還是客戶端解析邏輯不對(duì)。接口返回的 JSON 在調(diào)試面板里先看一遍再讓前端去對(duì)接溝通成本低很多。從那以后我每次接手 XData 項(xiàng)目都會(huì)強(qiáng)制自己先把/tms/xdata/info、實(shí)體映射、調(diào)試面板這三件事走一遍確認(rèn)環(huán)境是健康的再去碰業(yè)務(wù)邏輯。希望這篇筆記能幫你少踩幾個(gè)坑把 XData 真正用起來(lái)。本文還有配套的精品資源點(diǎn)擊獲取