Class Api<P,R>
- Type Parameters:
P- 负载类型R- 返回类型
- Direct Known Subclasses:
GetStatusApi,PlatformApi,SendCommandApi,SendRconCommandApi
一个 Api 就是一个可被客户端调用的协议接口。它自描述——名字由 name() 声明,
别名由 aliases() 声明,而不是在外部注册表里配对,因此新增 api 不需要修改路由代码。
负载解析由框架代劳:execute(JsonElement) 是 final 模板方法,
负责把原始 JSON 解析成 payloadType 并做错误映射;
子类只需实现 doExecute(Object) 处理已经解析好的负载。
平台结果统一转换:平台能力统一返回 PlatformResult,
子类用 requireSuccess(PlatformResult) 取成功数据即可,失败会自动转成
ProtocolException。通用映射由 mapPlatformResult(PlatformResult) 提供,
只有需要特殊协议语义的 Api 才覆盖它——不要在 doExecute 里写完整的 switch。
依赖由子类自行注入:本基类只持有 Logger 这一项基础设施,
不持有任何平台能力。Logger 是输出通道而非能力——持有它无法对世界产生副作用,
因此不构成"每个 Api 都能看见全部能力"的隐式耦合;真正需要平台能力的 Api
请继承 PlatformApi,其余依赖仍在子类构造器里显式接收。
日志使用约定:基类提供 logger 是为了让每个 Api 都有能力打日志,
而不是要求每个 Api 都必须打日志。只在有诊断价值的位置输出,
不要为每次调用机械补一行日志。级别建议:
debug—— 正常流程细节(收到请求、命中缓存);可能被高频轮询的接口一律用 debuginfo—— 状态变更(如已广播、已执行 Rcon 命令)warn—— 被拒绝的请求(参数非法、平台不支持)error—— 未预期异常;此类日志由ProtocolRouter统一记录,子类一般不必重复
线程安全约束(重要):Api 实例由 ProtocolRouter 在构造阶段创建一次,
随后在多个连接、多个线程之间共享。因此实现必须无状态——
不得持有任何随请求变化的字段。全部输入应来自方法参数,输出通过返回值表达。
违反该约束会引入静默的数据竞争:不同连接的请求会互相污染中间状态。
不访问静态全局状态:所有依赖(含 Logger)应由构造器注入,
否则协议层将无法脱离全局上下文独立测试。
-
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionaliases()别名protected abstract R处理已经解析好的负载final Rexecute(com.google.gson.JsonElement data) 处理一个请求protected ProtocolExceptionmapPlatformResult(PlatformResult<?> result) 把平台失败结果映射为协议异常abstract Stringname()协议api字段的主名字,例如"broadcast"protected final <T> TrequireSuccess(PlatformResult<T> result) 取出平台操作的成功数据;失败时抛出由mapPlatformResult(PlatformResult)映射的协议异常
-
Field Details
-
logger
protected final org.slf4j.Logger logger日志实现基类唯一持有的非负载依赖,由创建方注入。 子类直接使用本字段,不应再自己保存一份。
-
-
Constructor Details
-
Api
- Parameters:
payloadType- 负载类型,不得为 nulllogger- 日志实现,不得为 null
-
-
Method Details
-
name
协议api字段的主名字,例如"broadcast"- Returns:
- api 名字
-
aliases
别名用于"同一操作有多个协议名"的情况,例如
broadcast与send_msg由同一个 Api 实例服务。- Returns:
- 别名集合,默认空集合
-
execute
处理一个请求模板方法:解析负载 → 委托
doExecute(Object)。子类不应覆盖。- Parameters:
data- 原始 JSON 负载,可为 null- Returns:
- 处理结果
- Throws:
ProtocolException- 请求不合法或处理失败
-
doExecute
处理已经解析好的负载- Parameters:
payload- 负载,永不为 null- Returns:
- 处理结果
- Throws:
ProtocolException- 处理失败
-
requireSuccess
取出平台操作的成功数据;失败时抛出由mapPlatformResult(PlatformResult)映射的协议异常- Type Parameters:
T- 数据类型- Parameters:
result- 平台结果,不得为 null- Returns:
- 成功数据(可能为 null,
Void场景) - Throws:
ProtocolException- 平台结果非成功时
-
mapPlatformResult
把平台失败结果映射为协议异常默认映射(Java 8 的传统 switch;状态码语义以
ProtocolException现有工厂为准):PlatformResultCode.INVALID_ARGUMENT→ 400PlatformResultCode.UNSUPPORTED→ 503(平台未实现该能力,等价于迁移前sendTitleComponent/sendActionBarComponent直接抛出的 503)PlatformResultCode.FAILED→ 500PlatformResultCode.PLAYER_NOT_FOUND→ 500(默认;需要特殊语义的 Api 应覆盖本方法)
覆盖而非替换:子类只处理自己关心的结果码,其余交回
super, 从而避免每个 Api 重复编写完整的 switch。- Parameters:
result- 平台失败结果,不得为 null- Returns:
- 对应的协议异常
-