HarmonyOS应用实战-启示散页-67-路由表别散在功能包:让 entry 统一声明 HSP 页面入口
HarmonyOS 应用实战 67:路由表别散在功能包,让 entry 统一声明 HSP 页面入口
HSP 可以提供页面和服务,但不应该自己决定宿主暴露哪些入口。功能包各自写pushPath,会让路由名、参数类型和下线策略散落;新增或删除页面时,编译可能通过,点击却没有反应。
本文解决四个问题:
- 区分 HSP 导出能力和 entry 暴露入口
- 把 RouteName 和参数类型收进公共层
- 让 entry 统一登记 HSP 页面
- 验证删除导出、缺参数和入口下线
HSP 页面不是宿主入口表
HSP 的职责是提供可复用能力,entry 的职责是决定应用对用户暴露什么。入口表散在 HSP 里,会倒置依赖方向。
故障链:HSP 新增页面并硬编码 route -> entry 不知道该入口 -> 下线功能时漏删跳转 -> 点击无响应HSP 提供能力,entry 决定入口。这个边界不清楚时,功能包会把路由名、参数校验和启停策略都写散。
公共层只放稳定路由协议
HAR 可以保存 RouteName 和参数类型,但不引入页面实现。这样 entry 和 HSP 都依赖协议,不互相依赖内部细节。
exportenumRouteName{Home='Home',DeckEdit='DeckEdit',Drawing='Drawing',FavoriteList='FavoriteList'}exportinterfaceDeckEditRouteParam{deckId:string;from:'home'|'selector'|'recovery';}公共层只放协议,是为了让 entry 和 HSP 共享稳定名字和参数类型,而不是让 HAR 依赖页面实现。
HSP 只导出 Builder,不注册宿主策略
HSP 可以导出页面 Builder 和服务,不决定是否启用、是否需要登录、参数是否允许为空。
export{DeckEditPageBuilder}from'./src/main/ets/pages/DeckEditPage';export{DrawingPageBuilder}from'./src/main/ets/pages/DrawingPage';export{DeckService}from'./src/main/ets/services/DeckService';HSP 导出 Builder 和服务即可。它不应该决定这个页面在宿主里是否可见,也不应该私自处理宿主级入口策略。
entry 的 HostRouteRegistry 集中声明入口
宿主登记入口时同时写 owner、启用状态和参数校验。
interfaceHostRouteRecord<T>{name:RouteName;ownerModule:'entry'|'libraryHSP';enabled:boolean;validate:(param:T)=>boolean;}consthostRoutes:HostRouteRecord<DeckEditRouteParam>[]=[{name:RouteName.DeckEdit,ownerModule:'libraryHSP',enabled:true,validate:(p)=>p.deckId.length>0}];HostRouteRegistry把 owner、启用状态和参数校验放在同一处,后续下线页面或调整入口时不会漏查。
pageMap 是唯一分发点
不管页面来自 entry 还是 HSP,都由 entry 的 Navigation 分发。这样入口审计、灰度和下线都在一个地方完成。
@BuilderfunctionpageMap(name:string,param:object){if(name===RouteName.DeckEdit){DeckEditPageBuilder(paramasDeckEditRouteParam);}elseif(name===RouteName.Drawing){DrawingPageBuilder(paramasDrawingParams);}}pageMap是唯一分发点后,跨包页面也能被统一审计。路由失败时可以先查宿主表,而不是在多个功能包里搜索字符串。
路由验证要故意拆掉一个入口
路由检查不能只点正常入口。要临时禁用某个 HostRouteRecord、传空 deckId、移除一个 HSP 导出,看宿主是否能给出可解释错误。
验证:禁用 DeckEdit 后按钮不可进入;缺 deckId 被 entry 拦截;移除 HSP Builder 时构建或启动检查能发现。故意拆掉一个入口的验证很有必要。正常点击能通,只能证明 happy path;禁用、缺参、移除导出才能证明边界可靠。
HSP 路由排查表
点了没反应,先查宿主入口表。
| 现象 | 先看哪里 | 处理 |
|---|---|---|
| 点击无响应 | hostRoutes enabled | 宿主开启入口 |
| 页面参数为空 | validate 是否覆盖 | entry 拦截参数 |
| HSP 反向依赖 entry | HSP 是否硬编码 route | 改为导出 Builder |
点击无响应通常不是按钮问题,而是宿主入口表、参数校验或 HSP 导出关系断了。按这个顺序排查会更快。
路由协议和页面实现分开审
跨 HSP 路由要分两次审查。第一次看协议:RouteName 是否稳定、参数类型是否在公共层、是否没有页面依赖。第二次看实现:HSP 是否只导出 Builder,entry 是否统一注册入口。
协议审查:HAR -> RouteName / Param 类型 实现审查:HSP -> Builder / Service 宿主审查:entry -> HostRouteRegistry / pageMap / validate这个顺序能防止把所有问题都归到“路由跳转失败”,也能快速定位是协议错、导出错还是宿主表漏了。
验证要包括下线场景
很多路由只在新增时被测,几乎不测下线。真实项目里更危险的是功能下线、HSP 改名、参数升级后旧入口还在。第 67 篇应该把这些场景写进验证。
| 场景 | 构造方式 | 通过标准 |
|---|---|---|
| 入口禁用 | enabled=false | 按钮不可进入或给出解释 |
| 参数升级 | 缺少新增字段 | validate 拦截,不进入页面 |
| HSP 导出移除 | 移除 Builder 导出 | 构建或启动检查能发现 |
| 路由名重名 | 注册重复 RouteName | HostRouteRegistry 拒绝 |
这比只点一次“编辑题库”更能证明路由表集中管理的价值。
交付记录写清三层 owner
最终说明不要只写“路由统一到 entry”。要写清 HAR、HSP、entry 三层各自承担什么,以及哪一层没有被当前会话验证。
| 层 | owner | 证据 |
|---|---|---|
| 协议 | HAR | RouteName 和参数类型 |
| 能力 | HSP | Builder 导出清单 |
| 宿主 | entry | HostRouteRegistry、pageMap、入口截图 |
如果没有跑构建,就不要说导出关系已被编译验证;如果没有点页面,就不要说路由交互已通过。
路由表还要服务权限和灰度
entry 集中声明 HSP 页面入口后,不只是避免字符串分散,还能统一处理权限、灰度和下线策略。比如某个导入页面只允许测试版本打开,或者某个诊断页只能从设置页进入,都应该写在宿主入口表里。
interfaceHostRoutePolicy{enabled:boolean;allowedFrom:Array<'home'|'settings'|'selector'|'diagnostics'>;buildType:'debug'|'release'|'all';}这段策略让路由表从“页面名字集合”升级为“宿主入口协议”。文章写到这一步,读者才能理解为什么路由表不该散在功能包里:功能包不知道宿主发布策略,也不应该决定 release 包里哪些入口可见。
人工评审时搜硬编码路由名
路由集中管理后,最直接的复查是搜索硬编码 route 字符串。页面里仍然到处写'DeckEdit'、'Drawing',说明协议没有真正收敛。
rg-n"'DeckEdit'|'Drawing'|'FavoriteList'|pushPath|pushDestination"entry hsp har命中结果不是全部错误,但应该分成三类:RouteName 定义处、HostRouteRegistry 注册处、页面调用封装处。除此之外的散落字符串都要解释原因。这样读者能把文章里的架构边界变成可执行审查,而不是停留在“entry 统一声明”这句口号。
跨 HSP 项目尤其需要这一步,因为功能包越多,路由字符串越容易在示例代码、测试入口和临时按钮里残留。集中表不只是写一份新文件,还要逐步清掉旧入口。
最后一项看页面下线是否可控
路由表集中以后,还要验证“下线”这件事是否可控。把某个页面从HostRouteRegistry标记为不可用后,首页按钮、设置入口、历史回跳和深层跳转都应该得到同一套处理:要么入口不可见,要么被宿主拦截并给出解释。若某个功能包还能绕过宿主直接打开页面,说明入口权仍然散在包内。这个场景比新增页面更能证明架构边界,因为发布后的风险往往来自旧入口残留,而不是新入口打不开。
如果这一步没有证据,文章最多说明“入口表设计合理”,不能说明 HSP 页面下线链路已经稳定。真正可交付的路由治理,必须同时证明新增、跳转、缺参和下线都回到 entry 的同一张表。
小结
跨 HSP 路由要让 entry 掌握入口表。HAR 定义协议,HSP 导出能力,entry 决定暴露和校验;这样拆包、下线、灰度和参数错误都能在宿主边界处理。