资讯动态

Tea 中间件机制深度解析:如何快速为仓颉 Web 框架打造请求拦截链

发布时间:2026/9/24 14:26:52 来源:尧图企业网站定制
Tea 中间件机制深度解析如何快速为仓颉 Web 框架打造请求拦截链【免费下载链接】tea仓颉语言轻量级的、函数式的、高效的HTTP Web后端框架项目地址: https://gitcode.com/Cangjie-SIG/teaTea是一个用仓颉Cangjie语言编写的轻量级、函数式、高效的 HTTP Web 后端框架。它的中间件Middleware机制让请求拦截链变得极其简单——你只需几行代码就能在任意路由前插入鉴权、日志、CORS、限流等逻辑而完全不必污染业务 Handler。本文带你从原理到实战一次看懂并亲手打造属于自己的请求拦截链。核心关键词Tea 中间件、仓颉 Web 框架请求拦截链、use 注册中间件、CORS 中间件、共享参数 set/get、钩子函数 Hooks一、什么是 Tea 中间件先看懂洋葱模型 中间件的本质是一层包裹在请求与响应外围的处理函数。一个请求进来后会依次剥开多个中间件当它最终到达业务 Handler 后又逐层回包——这就是经典的洋葱模型Onion Model。在 Tea 里中间件和 Handler 是同一种东西public type HandlerFunc (TeaContext) - Unit // 接收上下文返回 Unit public open class Handler { ... } // 仿函数可携带元信息 metaData每个中间件接收一个TeaContext下文简称c代表当前请求的完整上下文。调用c.next()→ 放行进入下一个中间件 / Handler。不调用c.next()→ 拦截链在此中断请求不会继续往下走。 一句话记忆next()是油门不调就是刹车。这是所有拦截能力鉴权拒绝、限流、错误兜底的来源。中间件的入口定义在 src/core.cjHandler作为仿函数还能携带metaData一个HashMap方便你给每个处理函数打标签。二、如何注册中间件use 方法的 3 种写法Tea 用use方法注册中间件实现在 src/tea.cj。按作用范围它有 3 种常见用法写法作用范围典型场景app.use { ... }全部路由、全部方法全局日志、统一 CORSapp.use(/api, { ... })仅匹配路径前缀/api接口鉴权group.use { ... }仅路由组内部版本分组/v1、/v2独立策略1. 全局中间件最简单let app Tea.default() // 为 app 下全部路由注册任意请求都会先经过它 app.use { c println( 收到请求 ${c.getMethod()}) c.next() // 必须调用否则会中断 }2. 按路径前缀注册// 只有 /admin 开头的路由才走这段中间件 app.use(/admin) { c // 校验管理员身份失败则不调用 c.next() 即可拦截 c.next() }3. 路由组Group中间件通过 src/group.cj 的use给整个版本组挂一套独立策略是组织多版本 API 的最佳实践let v1 app.group(/api/v1) { c c.set(version, v1) // 给整组打标签 c.next() } v1.get(/list) { c /* ... */ }✅ 小提示use注册的是通配方法路由意味着它对 GET/POST/PUT 等所有 HTTP 方法都生效无需为每个方法单独注册。三、请求拦截链是如何执行的next() 逐层拆解 很多人只记住了c.next()却不知道它背后是两级推进。我们把执行引擎拆开看你就彻底懂了。第一级TeaContext.next()中间件内部推进源码见 src/context.cjpublic func next(): Unit { this.indexHandler // 指针 1 if (this.indexHandler this.route.handlers.size) { this.route.handlersthis.indexHandler // 执行“下一个” return } this.app.next(this) // 本路由用完 → 交给 Tea }当前路由上挂着一串handlers中间件 主 Handler 排成一队。每调一次next()indexHandler前进一格执行队列中的下一个函数。第二级Tea.next()路由之间推进当一个路由的 handlers 全部用完会调用 src/tea.cj 的next()func next(ctx: TeaContext): Unit { // 1. 按 method 前缀树取出候选路由列表 // 2. 逐个尝试 matchPath 匹配 // 3. 命中后ctx.indexHandler 0执行 handlers[0] // 4. 都没命中抛出 404 }为什么中间件一定在 Handler 之前答案在注册逻辑 src/tea.cjlet handlers ArrayListHandler() if (middleware.size 0) { handlers.add(all: middleware) // ① 先放中间件 } if (handler.isSome()) { handlers.add(handler.getOrThrow()) // ② 再放主 Handler }中间件永远排在主 Handler 前面——这正是拦截二字的由来它们先于业务逻辑执行也先有机会截停请求。四、在中间件之间传递数据set 与 get 共享参数 同一条拦截链上的所有函数共享同一个TeaContext。想把上游算出来的东西交给下游用set/get即可实现在 src/context.cj底层是一个ConcurrentHashMap。app.use { c c.set(userId, u-10086) // 上游写入共享参数 c.next() } app.get(/test) { c let uid c.get(userId) // 下游读取 c.sendString(hello ${uid}) // hello u-10086 }典型用途认证中间件把登录用户信息set进上下文后续所有 Handler 直接get取用避免重复解析 Token。 注意set的 value 是Any类型取出后通常需要as转型如book as String。五、实战用内置 CORS 中间件拦截跨域请求 ️Tea 自带一个非常完整的CORS 跨域中间件位于 src/middleware/cors/cors.cj。它是中间件能力的最佳样板——一个函数搞定预检请求OPTIONS、来源白名单、凭证控制。它拦截了什么读取请求头Origin比对白名单allowOrigins支持*与://*.通配子域。遇到OPTIONS预检 → 直接返回204 No Content不调用c.next()把跨域请求就地拦截。普通请求 → 写入Access-Control-Allow-*系列响应头后c.next()放行。核心拦截片段src/middleware/cors/cors.cj// OPTIONS 预检且无方法头 → 直接放行给后续 if (c.getMethod() MethodOptions c.getRequestHeader(HeaderAccessControlRequestMethod) ) { c.vary(HeaderOrigin) return c.next() } // ... 校验来源、设置响应头 ... return c.sendStatus(StatusNoContent) // 拦截不进入业务怎么用只需 3 行import tea.middleware.cors.cors let app Tea.default() app.use(cors(CorsConfig(allowOrigins: [https://example.com]))) app.get(/) { c c.sendString(ok) } app.run(8080)✅ 这让你零成本获得生产级跨域拦截——来源校验、预检响应、Credentials互斥校验*与凭证不可并存会直接抛错全部内置。六、进阶中间件 vs 钩子函数 Hooks 的区别 ⚙️Tea 除了请求期的中间件还提供 6 类生命周期钩子Hooks定义在 src/hooks.cj。它们的作用时机完全不同维度中间件use / next钩子函数Hooks触发时机每个 HTTP 请求框架生命周期节点典型用途鉴权、日志、CORS、限流路由/分组注册监听、启动、关闭能否拦截请求✅ 能不调 next 即拦截❌ 否只做旁路通知6 类钩子一览OnRoute/OnName—— 添加 / 命名路由之后OnGroup/OnGroupName—— 添加 / 命名分组之后OnListen—— 启动监听之前OnShutdown—— 调用shutDown()时app.hooks.registerOnListen { println(即将启动可在此做预热 / 校验) } 选型口诀要拦截请求 → 用中间件要监听框架事件 → 用 Hooks。七、错误兜底中间件抛异常怎么办拦截链中任何函数抛出异常都不会让服务崩掉——Tea 在请求入口处统一捕获并交给错误处理器src/tea.cj、src/tea.cjtry { next(ctx) } catch (e: Exception) { // 有错误没被处理 → 调用 errorHandler if (!ctx.app.handlerError(ctx, e)) { throw e // 处理器返回 false 才继续抛 } }默认defaultErrorHandler会读取Error中的状态码回写5xx响应体并返回true表示已兜底。你可通过TeaConfig.errorHandler自定义比如统一返回 JSON 错误结构、打日志、埋点。 配合中间件你可以在最外层写一个异常日志中间件再交给errorHandler统一格式化响应形成记录 → 兜底的完整闭环。八、快速上手清单5 步打造拦截链✅构造应用let app Tea.default()src/tea.cj。挂全局中间件app.use { c ... ; c.next() }做统一日志。按前缀加固app.use(/admin) { ... }做鉴权拦截。组内共享用c.set / c.get在拦截链中传递用户态。接入 CORSapp.use(cors(CorsConfig(...)))一键跨域。 更多 API 细节路由参数、配置项、常量可查阅 README.md完整示例见 src/test/tea_test.cj 与 src/test/cors_test.cj架构设计说明见 doc/design.md。写在最后Tea 的中间件机制把洋葱模型做得极其克制一个next()贯穿两级推进一个set/get完成数据流转一个use覆盖全局 / 前缀 / 分组三种作用域。理解这三点后你就能为仓颉 Web 框架搭建出既灵活又安全、层层可控的请求拦截链。【免费下载链接】tea仓颉语言轻量级的、函数式的、高效的HTTP Web后端框架项目地址: https://gitcode.com/Cangjie-SIG/tea创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价