开发手记 · 第 7 / 11 篇 合集目录 ‹ 上一篇 下一篇 ›

翻这套工业数据 WebApi 时,我发现每个请求进来都要过几道"关"。验身份、管加解密、记耗时——这些事跟具体业务没关系,但每个接口都得做。这类跟业务无关、却每个接口都要做的事,最怕各写各的:口径不一,出了事谁都说不清。

我早年写接口,把这些逻辑直接塞进每个 Controller,复制粘贴得到处都是,改一处得改十处。有回要加一道新安检,漏了该加的接口,出了岔子才回头补。这套平台把这类逻辑收成了一条通道。

(等价改写,名字换掉了)

// 每道安检从同一套模板长出来,长相一致好替换
public abstract class CheckFilter : IActionFilter {
    public void OnExecuting(Ctx c) {
        if (c.Has<SkipAttribute>()) return;  // 贴"免检"就跳过
        DoCheck(c);                          // 子类写具体安检
    }
    protected abstract void DoCheck(Ctx c);
}

每道安检是个可插拔的过滤器,统一从一套模板长出来。我在代码里数到 Filter 相关的接口有 28 处,全仓的安检逻辑都挂在这条通道上,没有一处散回业务层。我年轻时以为复制粘贴最省事,后来才知道,重复才是最大的坑——改一处要找十处,漏一处就出事。通道把"每个请求都该做的事"收成一条,谁过哪道关一目了然。

更妙的是它能"按门决定开不开":给某个接口贴个免检标签,这道关就跳过它;或者要求"必须带了某标签才放行"。敏感逻辑(比如加密、数据安全)则只放在通道层统一做,业务代码根本不碰——规则写在走廊上,房子里的人不用操心。

我后来规定,这类横切的事一律不准进业务层。默认每个请求都过安检,特例才贴免检——比写进每个房间干净一百倍。我踩过漏加安检的坑,所以现在格外较真这道关:默认都过、特例才免,比"要不要验"默认关更省心。