Api 设计,为什么契约在内部和外部都如此重要?
ApiHug 如何通过契约消除内部与外部之间的鸿沟
基础概念
为什么契约在内部和外部通信中如此重要?
本质上,ApiHug 所要解决的是 API 的问题,API 是用于不同层级或系统之间通信的一种规范。
换句话说,它就是一种契约:
- 在应用内部,用于后端与前端之间的通信;
- 在外部,则用于不同应用(微服务)或第三方系统之间的通信。
ApiHug 的实现方式
ApiHug 在设计中广泛使用契约机制:
- ApiHug 严格按照 Swagger 标准进行 API 设计;
- ApiHug 使用 DSL 定义契约提供方,这能充分利用编译期静态检查,避免人为错误并提升可读性;
- 对于第三方系统的依赖,同样采用 DSL 进行定义;
- ApiHug 的测试工具 Kola 严格基于 API 设计原型执行测试;
- ApiHug 通过 MCP 暴露 MCP 端点。
以上所有功能均基于 ApiHug 的 API 设计元语言:protobuf 构建。
在编译期和运行时阶段,你可以通过 hope.common.service.contract.ContractAdapter 轻松地自定义这些行为。
ApiHug 采用 service locator 在运行和编译时候加载你定制 Contract Adapter。
需要您:
- 保持自定义
ContractAdapter无状态,默认构建函数 - 在
{APP-MODULE}/src/main/resources/META-INF下创建 文件hope.common.service.contract.ContractAdapter登记您ContractAdapter:
#PKG-NAME#.infra.contract.MyContractAdapter
该适配器提供了以下扩展点以供定制化使用:
| 函数名 | 备注 |
|---|---|
moduleClassName | 当前应用程序 proto 模块的类名。 |
contract | 控制第三方模块(微服务 API 依赖)中暴露的 API 上下文信息。 |
mcp | 基于 API 控制是否暴露 MCP 服务。 |
如何通过 DSL 管理跨应用或 MCP 暴露时的 ApiContext:
- 使用
instance of将模块转换为指定的目标模块 - 利用 DSL 启用或禁用特定的服务或 API
//if module instanceof MyModule myModule:
return myModule.service()
.apiContext()
.orderService(
svc -> {
// Keep all the methods of this service
svc.keepAll();
// All the method start with, feel free try other shortcut
svc.startsWith("add");
// Pick method one by one
svc.methods(
methods -> {
// Include this method
methods.PlaceOrder();
// Exclude this method, start with `_`
methods._DeleteOrder();
});
})
.build();