
一次绕过业务网关的排障Spring MVC 微服务接口为何必须分层Spring MVC 项目最容易出现的结构退化是 Controller 从协议入口逐渐变成业务编排中心校验、转换、权限、事务和数据库调用全部堆在一个方法里。代码仍然能运行但任何复用都会绕回 HTTP 层。简单的“三层架构”名称并不能解决问题关键是外部协议何时结束、内部业务契约从哪里开始以及横切规则由谁执行。边界不清时网关与服务会同时校验又同时遗漏。MetaLite 把外网 Gateway、内部 Controller 与 Service 分别用于协议治理、内部契约和业务实现并用处理器链承接通用安全逻辑。本文从一次绕过网关的排障路径进入再以实际调用链说明三层各自不能承担什么。一、网关 Controller 只负责外部协议以backend-gateway的SysUserApi.createUser为例方法接收ExternalLoginBizParamReqSaveSysUserParam它不直接写用户表而是构造RpcRequestreturninternalServiceClient.callOneInstanceRtnData(RpcRequest.builder().provider(admin).endpoint(WebUtil.getRequestUri()).param(WebUtil.genInternalReq(req,SaveSysUserParam.class)).build(),Void.class);网关层的职责是维护公网契约、完成认证与协议转换然后选择内部服务实例。业务规则不应在这里复制一份否则网关和业务服务会逐渐出现两套判断。二、内部 Controller 为什么仍然有价值backend-admin中存在相同路径的SysUserApi.createUser但参数换成InternalBizParamReqSaveSysUserParam它只提取业务参数并调用returnsysUserService.createUser(req.getBizParam());内部 Controller 看起来很薄却建立了清晰边界HTTP 反序列化、Bean Validation、内部调用者信息属于接口层创建用户、唯一性校验、事务和缓存刷新属于 Service。薄 Controller 不是没有设计而是把变化频率不同的职责隔离开。三、为什么外部和内部可以使用相同 URIMetaLite 的网关和业务服务都声明/api/admin/sys/user/create。网关通过WebUtil.getRequestUri()把当前路径作为 RPC endpoint 转发。这样做的优点是外部与内部接口不用维护路径映射表日志按同一 URI 检索新增接口时转发代码更直观。代价是部署边界必须严格业务服务端口不能直接暴露给不可信网络。否则调用方可能绕过网关的认证、限流、解密和权限处理器直接访问内部 Controller。相同 URI 是降低映射成本的约定不是安全隔离措施。四、Service 为什么不能返回任意异常Service 可以返回Resp表达可预期业务失败也可以抛ServiceException交给统一错误体系转换。入口层负责把异常变成协议响应RPC 调用层则要保留失败语义不能把所有异常都吞成“调用失败”。这种边界让 Service 不需要知道当前请求来自浏览器、开放 API 还是其他微服务。但团队必须统一一种主要风格。若同类校验有时返回Resp.error、有时抛异常事务回滚和调用方处理会变得难以预测。五、BindingResult 为什么可以出现在签名里却不手工判断MetaLite Controller 保留隐藏的BindingResult参数校验由 API 切面中的ApiReceiveParamHandler统一读取和转换。这样每个方法不再重复if(bindingResult.hasErrors()){...}前提是接口必须经过对应切面。脱离该入口链单独调用 Controller不能假设校验错误仍会以相同方式处理。六、网关编排业务副作用要克制登录接口在 RPC 成功后调用userAuthService.afterLogin(loginResp)由网关写入登录 Token。这属于协议与会话边界放在网关有合理性。但订单创建、库存扣减等领域副作用不应采用同样方式堆在网关。网关一旦承担跨服务业务事务就会变成新的大单体。判断标准是这项逻辑是在维护外部协议与安全会话还是在实现领域业务规则。七、这套分层不等于 Spring Cloud GatewayMetaLite 使用的是显式 Spring MVC 业务网关不是根据路由表动态转发所有流量的 Spring Cloud Gateway。每个外部接口都有明确 Controller并显式构造内部请求。它适合需要强协议治理、请求模型转换和业务化安全处理的管理系统如果目标是高吞吐通用反向代理、WebSocket 或动态路由仍应评估专业网关。八、一套可执行的接口分层规则可以把职责约束为层应负责不应负责网关入口公网协议、认证、签名、加解密、限流、转发数据库事务、领域规则内部 Controller内网协议、参数校验、Service 调用重复网关安全逻辑、复杂业务Service业务规则、事务、缓存与跨 DAO 协调HTTP 请求对象、网关密钥DAO查询、更新与数据路由登录状态、接口响应拼装MetaLite 的核心不是多写一层 Controller而是让每一层的失败都能定位到协议、安全、业务或数据访问中的一个明确位置。九、用一次“绕过网关”实验验证分层边界这篇文章与接口规范总纲的区别不在于再画一遍分层图而在于验证一旦绕过业务网关哪些安全前提会立即失效。可以准备同一个创建用户请求分别走两条路径请求路径请求内容预期结果正常公网入口调用backend-gateway携带外部请求模型网关完成调用方认证、用户认证和协议转换再调用内部服务直接访问 Admin直接请求内部 URI不带可信内部上下文生产网络应拒绝访问而不是依赖 Controller 自己猜测来源伪造内部 Header公网请求自行添加用户 Header入口代理必须删除或覆盖后端端口不得直接暴露网关与内部 URI 不一致修改任意一侧映射WebUtil.getRequestUri()转发后无法命中集成测试应立即失败这组实验揭示了三个必须同时成立的条件公网只能到达网关内部 Header 只能由可信调用链写入网关和内部 Controller 的契约必须由测试锁定。只讨论 Controller 是否“薄”无法证明这套分层真的安全。建议把上述四种请求加入部署验收而不只运行单元测试。这样 045 关注的是边界被绕过时怎样失败095 则继续承担完整接口规范总纲两篇文章不再重复。框架简介MetaLite 是面向企业生产环境的新一代 Java 微服务技术底座。系列文章重点分享代码背后的设计思路、技术取舍与工程实践。源码基线JDK 21、Spring Boot 3.2.9、Spring Cloud 2023.0.1、Spring Cloud Alibaba 2023.0.1.3具体组件版本以项目backend-bom为准。作者简介15 年 Spring 体系企业级开发经验专注于 Java 微服务架构、工程治理与生产实践。持续更新MetaLite 系列内容将持续更新围绕核心设计、源码链路、技术取舍与生产实践展开。欢迎关注作者及时获取后续内容。在线演示演示地址: https://admin.metalite.top/演示账号: guess演示密码: admin2026