Skip to content

参数路由与路径段解析

简介

从 v1.0.0.420 起,HttpServer 新增了两个重要特性:

  • 参数路由 — 在 URL 路径中使用 {param} 语法定义动态参数段,类似 Laravel、Express 等现代框架
  • PathInfoList — 将 URL 路径按 / 分割为可按索引/按键访问的集合对象

两者配合使用,可以轻松构建 RESTful 风格的 API。


一、参数路由

1.1 基本用法

在路由注册时,使用 {参数名} 标记动态段:

vb
' 单参数路由
Call Server.Router.Add("/api/user/{id}", "UserController@Show", OnlyGet)

' 多参数路由
Call Server.Router.Add("/api/user/{userId}/post/{postId}", "PostController@Show", OnlyGet)

' 嵌套资源路由
Call Server.Router.Add("/api/group/{groupId}/user/{userId}", "GroupCtrl@Detail", OnlyGet)

1.2 控制器中获取参数

通过 ctx.Request.RouteParams 字典获取匹配到的参数值:

vb
' 单参数示例:GET /api/user/123
Public Sub Show(ctx As cHttpServerContext)
    Dim userId As String
    userId = ctx.Request.RouteParams("id")     ' 值为 "123"

    ctx.Response.Json Array("userId" & userId)
End Sub

' 多参数示例:GET /api/user/456/post/789
Public Sub ShowPost(ctx As cHttpServerContext)
    Dim userId As String, postId As String
    userId = ctx.Request.RouteParams("userId") ' 值为 "456"
    postId = ctx.Request.RouteParams("postId") ' 值为 "789"

    ctx.Response.Json Array(userId, postId)
End Sub

1.3 RouteParams 属性

vb
Public RouteParams As New Scripting.Dictionary
操作用法说明
获取参数ctx.Request.RouteParams("id")返回参数值字符串
检查存在ctx.Request.RouteParams.Exists("id")返回 Boolean
参数数量ctx.Request.RouteParams.Count未匹配参数路由时为 0
遍历参数For Each k In RouteParams.Keys遍历所有参数名

注意:如果没有匹配参数路由,RouteParams 为空字典(Count = 0)。

1.4 匹配规则

规则说明示例
参数段 {name}匹配任意非空字符串/api/user/{id} 匹配 /api/user/123
固定段必须精确匹配(忽略大小写)/api/user/{id}apiuser 是固定段
段数一致路径段数必须与模式段数相同/api/user/{id} 是3段,不匹配 /api/user/123/edit(4段)
参数非空参数段不能匹配空值/api/user/ 不匹配 /api/user/{id}

匹配示例

路由模式请求路径匹配结果RouteParams
/api/user/{id}/api/user/123{"id": "123"}
/api/user/{id}/api/user/abc{"id": "abc"}
/api/user/{id}/api/user/❌ 段数不一致
/api/user/{id}/api/users/123❌ 固定段不匹配
/api/user/{userId}/post/{postId}/api/user/456/post/789{"userId": "456", "postId": "789"}

1.5 匹配优先级

路由匹配按以下优先级执行:

  1. 精确匹配 — O(1) 字典查找,性能最高。如 /api/users 直接命中
  2. ANY 精确匹配 — 在 ANY 方法字典中查找
  3. 参数路由匹配 — 遍历含 {param} 的路由项,逐段模式匹配

精确路由永远优先于参数路由,不会因为参数通配而误匹配。

vb
' 同时注册精确路由和参数路由
Call Server.Router.Add("/api/user/me", "User@Me", OnlyGet)       ' 精确匹配优先
Call Server.Router.Add("/api/user/{id}", "User@Show", OnlyGet)   ' 参数路由次之

' GET /api/user/me   → 命中精确路由,调用 User@Me
' GET /api/user/123  → 命中参数路由,RouteParams("id") = "123"

1.6 参数路由 vs 查询参数

对比项参数路由查询参数
URL 格式/api/user/123/api/user?id=123
获取方式ctx.Request.RouteParams("id")ctx.Request.QueryString("id")
RESTful 风格✅ 符合❌ 不符合
SEO 友好✅ 更友好一般
可选参数段数必须一致天然可选
适用场景资源标识、层级路径筛选、分页、排序

两者可以组合使用:

vb
' GET /api/user/123/posts?page=2&limit=10
Call Server.Router.Add("/api/user/{id}/posts", "Post@List", OnlyGet)

Public Sub List(ctx As cHttpServerContext)
    Dim userId As String: userId = ctx.Request.RouteParams("id")
    Dim page As String: page = ctx.Request.QueryString("page")
    Dim limit As String: limit = ctx.Request.QueryString("limit")
End Sub

1.7 完整 RESTful API 示例

vb
' 注册控制器
Call Server.Router.Reg("Product", New cProductController)

' 列表:GET /products
Call Server.Router.Add("/products", "Product@List", OnlyGet)

' 详情:GET /products/123
Call Server.Router.Add("/products/{id}", "Product@Detail", OnlyGet)

' 创建:POST /products
Call Server.Router.Add("/products", "Product@Create", OnlyPost)

' 更新:PUT /products/123
Call Server.Router.Add("/products/{id}", "Product@Update", OnlyPut)

' 删除:DELETE /products/123
Call Server.Router.Add("/products/{id}", "Product@Delete", OnlyDelete)

' 子资源:GET /products/123/reviews
Call Server.Router.Add("/products/{id}/reviews", "Product@Reviews", OnlyGet)

' 子资源详情:GET /products/123/reviews/456
Call Server.Router.Add("/products/{productId}/reviews/{reviewId}", "Product@ReviewDetail", OnlyGet)

1.8 内部实现

参数路由由 cHttpServerRouteItem 类实现,核心机制:

  1. 注册时:调用 Init 方法,将路由模式拆分为路径段数组,提取 {param} 参数名
  2. 匹配时:调用 Match 方法,逐段比对——固定段忽略大小写精确匹配,参数段匹配任意非空值
  3. 参数提取:匹配成功后,参数名和值写入 Request.RouteParams 字典
路由模式: /api/user/{id}/post/{postId}
  ↓ Init() 拆分
段数组: ["api", "user", "{id}", "post", "{postId}"]
参数名: ["id", "postId"]

请求路径: /api/user/123/post/456
  ↓ Match() 逐段匹配
"api"      = "api"    ✅ 固定段匹配
"user"     = "user"   ✅ 固定段匹配
"{id}"     = "123"    ✅ 参数段 → RouteParams("id") = "123"
"post"     = "post"   ✅ 固定段匹配
"{postId}" = "456"    ✅ 参数段 → RouteParams("postId") = "456"

二、PathInfoList 路径段集合

2.1 简介

PathInfoListcCollection 类型的集合对象,在请求解析时自动将 URL 路径按 / 分割,每一段存入集合,键和值都是段名,支持按索引和按键访问。

vb
Public PathInfoList As New cCollection

2.2 使用示例

vb
' 请求:GET /api/user/list?page=1

' ── 按索引访问(1-based) ──
MsgBox ctx.Request.PathInfoList(1)     ' → "api"
MsgBox ctx.Request.PathInfoList(2)     ' → "user"
MsgBox ctx.Request.PathInfoList(3)     ' → "list"

' ── 获取路径段数 ──
MsgBox ctx.Request.PathInfoList.Count  ' → 3

' ── 按键访问(键=值=段名) ──
MsgBox ctx.Request.PathInfoList("api") ' → "api"

' ── 判断路径中是否包含某段 ──
If ctx.Request.PathInfoList.Exists("api") Then
    Debug.Print "路径包含 api 段"
End If

' ── 遍历所有路径段 ──
Dim i As Long
For i = 1 To ctx.Request.PathInfoList.Count
    Debug.Print "段" & i & ": " & ctx.Request.PathInfoList(i)
Next i

2.3 常见路径的 PathInfoList

请求路径PathInfoList.CountPathInfoList(1)PathInfoList(2)PathInfoList(3)
/0
/api1"api"
/api/user2"api""user"
/api/user/list3"api""user""list"
/api/user/1233"api""user""123"

2.4 典型应用场景

vb
' 判断是否是 API 请求
If ctx.Request.PathInfoList.Count > 0 Then
    If ctx.Request.PathInfoList(1) = "api" Then
        ' 处理 API 请求
    End If
End If

' 获取路径中的资源 ID(配合参数路由更佳)
If ctx.Request.PathInfoList.Count >= 3 Then
    If ctx.Request.PathInfoList(2) = "user" Then
        Dim userId As String
        userId = ctx.Request.PathInfoList(3)   ' 如 "123"
    End If
End If

' 建议优先使用参数路由获取 ID:
' userId = ctx.Request.RouteParams("id")

提示:对于获取路径中的动态参数(如用户ID),建议优先使用参数路由的 RouteParams,语义更清晰且类型安全。


三、新增文件清单

文件类型说明
cHttpServerRouteItem.cls新增路由项类:解析 {param} 模式、匹配路径、提取参数
cHttpServerRouter.cls修改路由匹配逻辑:精确匹配优先,参数路由次之
cHttpServerRequest.cls修改新增 RouteParams(Dictionary)和 PathInfoList(cCollection)

100% 向后兼容——已有的精确路由注册和匹配不受任何影响。


最后更新: 2026-06-11

VB6及其LOGO版权为微软公司所有