隨著微服務架構演進,企業級應用常面臨:統一權限校驗、灰度發布路由、全鏈路流量監控等橫切關注點。構建一層「透明傳輸網關」——不解析具體業務參數,僅按路由規則轉發請求至下游服務,成為通用解決方案。Spring MVC 凭藉靈活的請求映射與 HttpServletRequest 底層訪問能力,極適合構建此類網關層。
下游服務 URL 結構多樣(/user/query、/order/detail/123、/product/list?page=1),無法逐一定義 Controller 方法。利用 Spring MVC @RequestMapping 的 Ant 風格通配符 /** 結合路徑變量:
@RequestMapping(value = "/{serviceName}/{methodName}/**", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public @ResponseBody Object getHttp(
@PathVariable("serviceName") String serviceName,
@PathVariable("methodName") String methodName,
HttpServletRequest request, HttpServletResponse response) {
// 提取實際下游路徑:request.getRequestURI().substring(...)
// 組裝下游完整 URL,透傳 Header/Query/String Body
return sendGetHttp(serviceName, methodName, request, response);
}
關鍵點:/** 匹配任意多級路徑;produces 統一響應編碼;異常統一捕獲並映射為標準錯誤碼(如 520 表示網關層異常)。
@RequestBody 陷阱網關層不應定義具體 DTO,否則會序列化/反序列化雙重開銷且破壞透明性。移除 @RequestBody 註解,直接從 HttpServletRequest 讀取輸入流:
private String resolveRequestToBody(HttpServletRequest request) throws IOException {
int length = request.getContentLength();
if (length <= 0) return null;
try (InputStream is = request.getInputStream()) {
byte[] bytes = new byte[length];
int read = is.read(bytes);
return new String(bytes, 0, read, StandardCharsets.UTF_8);
}
}
注意:InputStream 只能讀取一次,若上游 Filter/Interceptor 已消費流,需提前用 ContentCachingRequestWrapper 緩存。POST/PUT/PATCH 等含 Body 請求均走此邏輯;GET/DELETE 無 Body 直接跳過。
Host、Content-Length 等跳躍頭,其餘原樣轉發(含認證 Token、TraceId)。request.getQueryString() 直接拼接至下游 URL。RestTemplate / WebClient 設置連接/讀取超時,配合 Resilience4j/Sentinel 做熔斷降級。Spring MVC 路徑匹配遵循 Ant 風格:? 匹配單字符,* 匹配單級路徑,** 匹配多級路徑。/{varName:regex} 支持正則約束變量格式。詳細規則參考 官方文檔與社區總結。
Spring MVC 透明傳輸層核心在於:通配符路由攔截全量請求 + 原始流讀取避免業務綁定 + 統一異常與編碼處理。此模式輕量級、零侵入,適合作為微服務網關、BFF 層或舊系統改造的防腐層。