概述
在後端與前端共同開發的過程中,消除重複撰寫相同 API 合約與類型的瓶頸,並將路由器·處理器·MongoDB 欄位字串等重複的開發工作轉變為基於來源的生成,說明其背景與原則。
起源故事
我同時處理後端和前端。在創建一個功能時,我需要在 Java WebFlux 中編寫端點和請求/響應 DTO,然後在前端再次編寫相同的 URL 和 TypeScript 類型。為了直接對齊 Swagger 文檔,我不得不將已存在於後端的信息以不同的格式再次轉移。
最大的瓶頸是將後端創建的 API 合約重新編寫為前端可以使用的形式。如果 URL、HTTP 方法、路徑/查詢參數或請求/響應結構中的任何一個在雙方之間有所不同,我們會在編譯後才發現問題。這不僅僅是麻煩的工作,還有因為同樣的內容由人員管理兩次而產生的不一致性問題。
我也想減少創建 RouterFunction 和處理程序時的重複。如果在路由器中添加了 ApiAccountHandler::search 這樣的引用,那麼不存在的處理程序類和方法骨架應該可以自動生成。在編寫 MongoDB 查詢時,像 "username" 這樣重複字符串的實體字段名稱也很繁瑣且容易出錯,因此我將讀取實體源並生成 Java 枚舉的功能也放在同一工具中。
因此,Swagger/OpenAPI 生成、處理程序骨架生成和 Mongo 實體字段枚舉生成首先完成,隨後在使用 RSocket 時也添加了 AsyncAPI 生成。雖然這些看起來是不同的想法,但出發點是相同的。讓機器代替人類創建可以被機器讀取的部分,而不是讓人類重複編寫已經在後端源中記錄的事實。
開發哲學
以後端源為基準
RouterFunction、處理程序、DTO 和實體中已存在的信息用作 API 文檔和生成代碼的原始資料。關鍵是不要在單獨的文件中重新管理相同的合約。
選擇開發時期自動化而非運行時魔法
不是攔截生產請求的框架,而是在本地開發環境中分析源並生成實際文件。可以目視檢查結果並進行版本控制。
遵循可預測的項目慣例
不以理解所有 Java 代碼的通用編譯器為目標。優先分析我實際使用的 WebFlux 功能端點結構,並制定明確的規則。
消除重複的連接區間
在後端端點生成 Swagger,前端生成器讀取該文檔以生成服務和類型,形成一個自動化鏈。
後端讀取什麼
RouterFunction 源
讀取 HTTP 方法、嵌套路徑、處理方法引用和謂詞。
處理器來源
讀取請求主體、查詢/路徑值和響應發布者類型。
請求/響應 DTO
將後端已編寫的 Java 類型連接到 OpenAPI 架構。
Mongo 實體來源
讀取 Java 欄位和 @Field 的存儲原始名稱,@Document 集合。
RSocket 控制器
讀取 @MessageMapping 路由和請求/響應有效載荷類型。
創造而非重複編寫什麼
swagger.json
將 REST 端點製作成前端服務和 TypeScript 類型生成器可以使用的 API 合約。
asyncapi-rsocket.json
將 RSocket 路由和有效載荷製作成前端 RSocket 客戶端生成器可以讀取的合約。
處理器來源
根據 RouterFunction 中首先寫的處理器引用生成和修正類別和方法骨架。
{Entity}Fields 列舉
將字符串欄位名稱轉換為枚舉,以避免重複實體的 Java 欄位和存儲原始名稱。
CollectionNames 列舉
生成可用於 @Document 中聲明的集合名稱的字符串。
當前專案中的自動化流程
• 在後端編寫 RouterFunction、處理器和 Java 請求/響應 DTO。
• 本地配置文件的監視器檢測到來源變更,更新 swagger.json 或 asyncapi-rsocket.json。
• 前端的 @byeolnaerim/typed-rx-http 生成腳本讀取文檔並生成服務函數和 TypeScript 類型。
• 在屏幕代碼中,通過導入生成的函數來使用,而不重新編寫 URL 和響應類型。
• 當實體變更時,查詢中使用的欄位枚舉和集合枚舉也會一起更新。