# 三层 API xly 不是只有一个 API,而是有**三层**,分别由三个独立的 Spring Boot 服务承载,面向不同受众,也有不同的运行契约。任何集成讨论的第一步,都是先确认你在和哪一层对话。 | 层级 | 服务 | Context path | 受众 | |---|---|---|---| | **内部** | `xlyEntry` | `/xlyEntry` | xly SPA 自身(BACK + FROUNT)。对外部调用方不是稳定契约。 | | **外部** | `xlyApi` | `/xlyApi` | 从外部调用 xly 的租户和集成方。数据驱动的公开 API。 | | **入站 webhook** | `xlyInterface` | `/xlyInterface` | 将事件推送进 xly 的第三方系统。带 Swagger。 | 每个服务都会构建成自己的 WAR,并在自己的 JVM 中运行。它们不共享进程内状态;它们共享的是**数据库**。正是这个共享数据库让服务拆分成立:内部 API 写入的数据会自动被外部 API 读到,因为两者都连接同一个 schema。 ## 为什么是三层,以及拆分的代价 每一层最初都是为了解答不同的问题: - **内部层**很大(对所有元数据驱动模块做通用 CRUD)、易变(随框架变化)、且有意保持弱类型(SPA 决定要什么,服务端照元数据执行)。 - **外部层**是收敛后的接口(只暴露允许集成方使用的端点),按 `sApiCode` 做版本化,并用 bearer token 认证。 - **入站 webhook 层**接收来自第三方系统的不可信 body,并路由到 xly 处理器。Swagger UI 放在这里,因为这个受众最需要交互式文档。 这个拆分有真实成本,Wiki 不应该略过: - **需要部署、监控、锁定版本的 WAR 有三个。** 一次发布必须协调 `xlyEntry`、`xlyApi`、`xlyInterface` 的构建。版本不匹配时(例如 `xlyEntry` 引入了 schema 变化,但 `xlyApi` 还没跟上),问题通常会静默存在,直到某条调用路径撞上它。 - **存在重复代码。** `RequestAddParamUtil` 在 `xlyPersist`(供 `xlyEntry` 使用)和 `xlyApi` 中各有一份,几乎是 56 行 / 57 行的拷贝。`InterfaceController` 在 `xlyApi` 和 `xlyInterface` 中也都存在,并且有重叠的 `/interfaceDefine/callthirdparty/*` 端点。让两边保持同步依赖运维纪律,不是编译期保证。 - **没有共享 session。** 在 BACK 登录的用户,在 `xlyApi` 中没有 session;外部调用方需要单独获取 bearer token。这对外部集成是正确的,但也意味着内部跨 WAR 调用如果发生,必须走公开 token 流程。 - **三个 context path 就意味着三条反向代理规则。** `BACK=:8597`、`FROUNT=:8598` 到具体 WAR 的映射在 nginx 配置中,不在本仓库里。代理配置错误是代码库本身捕捉不到的常见故障模式。 这些层当然也可以做成一个部署物,只在内部用包边界隔离;Spring Boot 支持这种做法。那样的好处是:一次构建、一套依赖、一套 session 逻辑,也不会有重复工具类。代价是:各层更难独立扩容,也更难只限制外部调用方而不影响 SPA。xly 选择了部署期隔离;Wiki 的职责是把这个选择牺牲了什么写清楚。 ## 每一层在运行时长什么样 - **内部层** — 见[五键读取](../reference/maintainer/runtime.md#five-key-read)。一个端点(`/business/getModelBysId`)返回完整表单布局;另一个端点(`/business/addUpdateDelBusinessData`)写入元数据命名的任意表中的任意行。端点少,形状通用。 - **外部层** — 大多数调用走 `/api/invoke/{sApiCode}`。`sApiCode` 是 `sysapi` 元数据表中的一行,定义 SQL 模板、参数、认证要求和目标。新的外部 API 是**注册成数据**,不是写成代码;这和框架对自身表单采用的数据驱动基本论点一致。 - **入站 webhook 层** — `/interfaceDefine/invoke/{interfaceInvoke}` 接收载荷,查找元数据中的匹配处理器,运行配置好的 SQL 或存储过程。此外还有少量为特定伙伴准备的硬编码接收器(`/Push`、`/Pull`、`/send/sendQw`)。 ## 下一步看哪里 - [API 参考(内部)](../api-reference/internal.md) — SPA 使用的 `xlyEntry` 端点;不面向外部调用方。 - [API 参考(外部)](../api-reference/external.md) — 集成方使用的 `xlyApi` 接口面,以及 `sysapi` 驱动的 `/api/invoke` 模式。 - [API 参考(Webhook)](../api-reference/webhooks.md) — `xlyInterface` 入站接口面,以及 Swagger UI 的服务地址。 - [API 参考(消息)](../api-reference/messaging.md) — 补充 HTTP API 的 ActiveMQ / RocketMQ 事件通道。