全解)
http_router路由匹配深度解析getHandler與RouterValueSetter提取路徑參數(shù)全解【免費下載鏈接】http_router提供標準化的路由注冊、路由匹配能力項目地址: https://gitcode.com/Cangjie-SIG/http_router如果你正在用倉頡語言開發(fā) Web 服務http_router就是一個專注于路由匹配的輕量工具給出一條 URL 路徑它能幫你快速找到對應的處理器函數(shù)并把路徑參數(shù)如/hello/Alice中的Alice自動提取出來。本文將帶你完整看懂兩個核心 APIgetHandler如何在路由樹中完成一次匹配返回處理器與重定向建議RouterValueSetter如何以key/value回調的形式提取路徑參數(shù)不需要任何前置經(jīng)驗跟著讀就能上手 http_router 是什么http_router 是一個倉頡開源包見 cjpm.toml組織為opencj當前版本 0.1.1參考了業(yè)界著名的 httprouter 設計把 Restful 路徑解析部分解耦出來只提供兩件事能力API說明 路由注冊Node.addHandler(path, handler)把路徑 → 處理器掛載到路由樹 路由匹配Node.getHandler(path, valueSetter)在路由樹中查找處理器并提取路徑參數(shù)處理器類型由泛型T決定你可以傳函數(shù)、方法甚至自定義類型靈活性很高。完整 API 說明見 README.md。理解路由樹Node 的 4 種節(jié)點類型http_router 內部把注冊過的所有路徑組織成一棵路由樹每個節(jié)點由Node表示。節(jié)點類型定義在 NodeType 中共 4 種節(jié)點類型含義典型例子Static靜態(tài)文本節(jié)點/file/uploadRoot根節(jié)點/Param參數(shù)節(jié)點:name/hello/:nameCatchAll通配節(jié)點*filepath/files/*filepath以注冊/hello/:name為例樹會被拆成/hello/靜態(tài)段 :name參數(shù)段。理解這一點后匹配過程其實就是從根節(jié)點一路向下走樹的過程。getHandler一行調用完成路由匹配核心簽名定義在 node.cj#L296-L305public func getHandler(path: String, valueSetter: ?RouterValueSetter): (?T, Bool)返回值是一個二元組初學者最容易困惑的就是它?T可空的處理器匹配成功返回對應處理器沒匹配到返回NoneBool尾斜杠重定向建議路徑本身沒命中但加個/或去掉/就能命中時為true方便你給出 301 重定向提示內部實現(xiàn)getHandlerWalk會循環(huán)消費剩余路徑逐段比對節(jié)點當請求路徑和當前節(jié)點路徑完全相等時即完成匹配。整個過程沒有字符串遍歷開銷是典型的前綴樹Trie查找思路。RouterValueSetter路徑參數(shù)提取全解RouterValueSetter的類型定義非常簡單見 types.cj#L33public type RouterValueSetter (key: String, value: String) - Unit它本質是一個回調函數(shù)匹配過程中每遇到一個路徑參數(shù)路由樹就會帶著參數(shù)名和參數(shù)值調用你。參數(shù)節(jié)點:name如何觸發(fā)當你用getHandler(/hello/changeden, setter)匹配已注冊的/hello/:name時走到Param節(jié)點會執(zhí)行 node.cj#L345-L347 的邏輯keyname冒號后的參數(shù)名valuechangedenURL 中該段的實際內容也就是說你不需要自己寫任何解析代碼參數(shù)在匹配的瞬間就被送進了回調。通配節(jié)點*filepath如何觸發(fā)通配參數(shù)會捕獲剩余全部路徑。在CatchAll分支見 node.cj#L374-L380例如注冊/files/*filepath請求/files/a/b.png時keyfilepathvaluea/b.png一個直觀的例子func getDefaultValueSetter(route: String): RouterValueSetter { { key, value println([${route}] key: ${key} , value: ${value}) } }這段代碼來自 main.cj#L77-L81。注冊/hello/:name后請求/hello/changeden控制臺就會打印[hello] key: name , value: changeden這就是匹配 參數(shù)提取一次調用完成的效果。實戰(zhàn)多請求方法的路由匹配實際 Web 服務中同一個路徑往往對應不同的請求方法GET/POST/PUT。main.cj 給出了完整的多節(jié)點示例用HashMapHttpMethod, NodeHandler為每種方法維護一棵獨立的路由樹。func registerHandler(rootMap: HashMapHttpMethod, NodeDefaultHandler, method: HttpMethod, path: String, h: DefaultHandler): Unit { if (!rootMap.contains(method)) { rootMap[method] NodeDefaultHandler() } rootMap[method].addHandler(path, h) }匹配時先用方法查到對應樹再調用getHandler即可見 main.cj#L69-L75。HttpMethod枚舉定義在同文件 L26-L59你可以按需擴展方法類型。開發(fā)調試時強烈推薦用 dump 打印整棵路由樹直觀查看節(jié)點劃分與類型dump(root)避坑指南注冊時的沖突規(guī)則http_router 對非法路由會直接panic拋異常把錯誤擋在啟動階段。以下是四條高頻規(guī)則同一路徑重復注冊一個路徑只能掛一個處理器重復注冊直接報錯node.cj#L167-L170一個路徑段只允許一個通配符/:a:b是非法的node.cj#L195-L203通配符必須命名/:這種空名字不允許node.cj#L212-L215CatchAll 只能放在路徑末尾/files/*filepath?/*filepath/files?node.cj#L247-L250 另外注意通配符與靜態(tài)子節(jié)點會沖突——如果/user已注冊子路由再注冊/user/:id會 panicnode.cj#L205-L210。設計 URL 時讓參數(shù)段與靜態(tài)段錯開即可??焖偕鲜? 步跑起來第一步獲取源碼git clone https://gitcode.com/Cangjie-SIG/http_router第二步構建項目項目使用 cjpm 管理見 cjpm.toml要求倉頡編譯器 1.1.0cjpm build第三步注冊 匹配 提取參數(shù)參考 README.md 單節(jié)點示例let root NodeDefaultHandler() root.addHandler(/, index) root.addHandler(/hello/:name, hello) let (handler, _) root.getHandler(/hello/changeden, getDefaultValueSetter(hello)) handler?()三步完成路由注冊、路由匹配、參數(shù)提取的完整閉環(huán) 總結要點一句話記憶NodeT路由樹節(jié)點泛型決定處理器類型addHandler把路徑掛到樹上沖突直接 panicgetHandler走樹匹配返回(處理器, 尾斜杠建議)RouterValueSetter(key, value)回調自動提取:name與*filepath參數(shù)dump調試利器一眼看清路由樹結構http_router 的設計哲學是少即是多不含 HTTP 框架的包袱只把路由注冊與匹配做到標準、快速、可組合。無論是嵌入你自己的 Web 框架還是做工具類應用它都是一個干凈可靠的底層構件?!久赓M下載鏈接】http_router提供標準化的路由注冊、路由匹配能力項目地址: https://gitcode.com/Cangjie-SIG/http_router創(chuàng)作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考