在 Vert.x 4.4.1 中使用 MVEL 模板引擎时,RoutingContext 对象本身不可直接在模板中通过 context 变量访问;实际注入模板的是 RoutingContext.data() 的内容,因此应直接使用键名(如 traducciones)引用已 put() 的数据。
在 vert.x 4.4.1 中使用 mvel 模板引擎时,`routingcontext` 对象本身不可直接在模板中通过 `context` 变量访问;实际注入模板的是 `routingcontext.data()` 的内容,因此应直接使用键名(如 `traducciones`)引用已 `put()` 的数据。
Vert.x 的模板渲染机制(尤其是 TemplateHandler 配合 MVELTemplateEngine)不会将完整的 RoutingContext 实例暴露给模板,而是仅将其内部的 data() 映射(即一个 Map
routingContext.put("traducciones", traducciones);等价于向模板作用域中添加了一个名为 "traducciones" 的变量,其值为 traducciones 对象。因此,在 index.tmpl 中应直接使用变量名,而非尝试通过 context.get(...) 访问:
✅ 正确写法(推荐):
<!-- 在 index.tmpl 中 -->
<h2>@{traducciones.welcome}</h2>
<p>@{traducciones.login_title}</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill5360" title="Skill Weave Chains — 技能链路由引擎"><img
src="https://img.php.cn/upload/skill/000/000/081/179047814579604.jpg" alt="Skill Weave Chains — 技能链路由引擎" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill5360" title="Skill Weave Chains — 技能链路由引擎">Skill Weave Chains — 技能链路由引擎</a>
<p>开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。</p>
</div>
<a href="/xiazai/skill5360" title="Skill Weave Chains — 技能链路由引擎" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div>❌ 错误写法(导致 PropertyAccessException: could not access: context):
@code{traducciones = context.get("traducciones")} // ❌ context 未定义!
@{context.get("traducciones").welcome} // ❌ 同样失败
@{context.request().path()} // ❌ request 不可用✅ 正确配置与使用示例
-
路由处理器中注入数据(确保在 TemplateHandler 前执行):
router.get("/login").handler(routingContext -> { Map<String, String> traducciones = loadTranslations(); // e.g., from JSON or DB routingContext.put("traducciones", traducciones); routingContext.put("pageTitle", "Iniciar sesión"); routingContext.put("showAdminSetup", !Users.existAdminUser()); if (Users.existAdminUser()) { routingContext.next(); // 继续到 TemplateHandler } else { routingContext.response() .setStatusCode(302) .putHeader("Location", "/accounts/register-admin") .end(); } }); // 必须在路由链后续添加 TemplateHandler router.get("/login").handler(TemplateHandler.create(MVELTemplateEngine.create(vertx))); -
模板中直接使用键名(index.tmpl):
<!DOCTYPE html> <html> <head><title>@{pageTitle}</title></head> <body> <h1>@{traducciones.title_login}</h1> <form action="/auth" method="post"> <input type="text" name="username" placeholder="@{traducciones.placeholder_username}" /> <input type="password" name="password" placeholder="@{traducciones.placeholder_password}" /> <button type="submit">@{traducciones.button_login}</button> </form> @if(showAdminSetup) { <p class="hint">@{traducciones.hint_admin_setup_required}</p> } </body> </html>
⚠️ 注意事项
- 顺序至关重要:routingContext.put(...) 必须在调用 routingContext.next() 前完成,且 TemplateHandler 必须是该路径上 next() 后触发的下一个处理器。
- 无 context 全局对象:MVEL 模板中不存在 context 变量——这是常见误解。Vert.x 文档中提及的 context.request() 等用法适用于其他模板引擎(如 Thymeleaf 或 Handlebars 的扩展),不适用于 MVEL。
-
类型安全建议:若 traducciones 是 Map
,可在模板中安全使用点号访问(如 traducciones.greeting);若为复杂对象,请确保其字段为 public 或提供 getter 方法(MVEL 支持 JavaBean 属性访问)。 -
调试技巧:临时在模板中输出全部数据以确认注入是否成功:
@code{print(data)} <!-- 查看当前作用域所有键 -->
✅ 总结
Vert.x 4.4.1 的 MVEL 模板引擎采用“扁平化数据注入”模型:仅 RoutingContext.data() 内容可用,且以裸键名(如 traducciones)直接引用。放弃任何对 context、request 或 session 的模板内访问尝试,转而通过 routingContext.put() 显式传入所需数据——这是简洁、可靠且符合 Vert.x 设计哲学的最佳实践。


















