引言
在 WebBuilder 中,"组件"不只存在于浏览器端。每个 .xwl 模块的根节点 Wb.Module 本身就是一个服务端组件:它有属性、有事件、有生命周期,能接收请求、执行脚本、访问数据库并输出数据。配合 Wb.sql 为核心的数据访问 API 族与 GraalVM 多语言运行时,服务端开发被压缩成"写一段 JS 就是一个接口"。本文解析这套服务端组件模型。
Wb.Module:请求即组件调用
客户端通过 Wb.ajax({url:'m?xwl=admin/user', params}) 或组件的 url 属性发起请求后,webbuilder-11.2.jar 中的 Filter 将请求交给模块执行器:定位 .xwl 文件 → 检查编译缓存 → 登录/权限检查 → 在执行上下文中运行 serverScript → 输出响应。模块根节点的 loginRequired: false 可豁免登录(如登录页自身)。服务端 app 对象贯穿整个上下文,承载请求参数、会话信息与组件引用;Wb.run('other.xwl') 可在模块间链式调用并传递数据,类似函数调用而非 HTTP 转发。
serverScript:服务端 JavaScript
模块的 properties.serverScript 是服务端脚本,运行于 GraalVM 引擎,被 JIT 编译到原生速度,并借助预缓存的执行上下文支持高并发。典型例子来自测试模块,全文仅一行:
Wb.sendSql 执行 SQL 并把结果按 {items, columns, fields, total} 约定输出,正好被 Wb.Grid 消费——前后端之间由数据约定而非接口文档连接。复杂逻辑则通过 Wb.apply(app, { afterAction(){...} }) 定义命名方法供前端回调调用,如报销流程中为新增行补齐 sid: Wb.getId()、flow_id、user_id: Wb.userid 后执行 Wb.sync({tableName:'wb_reimburse', ...data}) 完成事务性落库。
Wb.sql 与数据访问 API 族
数据访问的核心是 Wb.sql:支持多语句执行与存储过程调用,返回 {items, columns, fields, total} 结构。围绕它衍生出 20 余个便捷 API:getRow/getRowx 取单行、sendRows/sendDict 直接送出数据、getRecords、sqlRS 等,覆盖查询结果的各种消费形态。SQL 中的参数占位语法值得专门记忆:{?varchar|name?} 声明输入参数,{*type|name*} 声明输出参数;参数值默认从 session/request 上下文自动获取,也允许显式传入,天然规避 SQL 注入。
连接管理同样组件化:Wb.getConn('db1') 从连接池(commons-dbcp2)取命名数据源连接,new Wb.Connection('db1') 建立受管连接。数据库在"管理工具/数据库配置"(admin/dbc.xwl)中注册并设为默认;平台自带 Derby 库(wb/system/db/derby)开箱即用,lib 目录中的 mysql-connector-j、ojdbc11、postgresql、mssql-jdbc 驱动表明主流数据库均可一键切换。
多语言互操作与系统 API
GraalVM 带来了多语言能力:Java.type('java.util.HashMap') 或 Packages. 前缀直接实例化 Java 类,Polyglot.eval('python', ...) 执行 Python 脚本(示例模块中有调用 demo.py 的完整演示)。系统级 API 也很完备:输出用 Wb.send / Wb.exportData / Wb.submit(POI/PDFbox 支撑 Excel/PDF 导出),实时推送用 Wb.send('text', 'mySocket') 走 WebSocket(配合客户端 Wb.Socket 组件),定时任务由 Quartz 驱动(admin/task.xwl),多线程用 Wb.poolStart,跨请求共享状态放 Base.map。
组织与安全
服务端模块按 wb/modules/ 目录分层:admin(管理工具)、dev(开发套件)、sys(登录会话/门户/文件/字典服务)、my(我的流程)、example、test。目录即权限边界——模块默认受保护,仅 $ 结尾文件可直接访问;每个请求都经过统一 Filter 的鉴权检查,业务代码无须重复编写权限逻辑。wb/system/url.json 还提供 /ide → dev/ide.xwl 式的 URL 别名,让对外接口保持稳定。
结语
Wb.Module 把"服务端"抽象成与前端同构的组件:一个文件、一个上下文、一组数据 API。声明式的参数绑定、约定式的数据结构、多语言运行时与统一鉴权,共同构成了 WebBuilder 服务端组件的技术底座——也是它能用极少量代码撑起完整业务系统的原因。