
在 Spring Boot 应用中,可通过自定义 Filter 为 /api/data/accept 等特定路径单独限制 POST 请求体大小(如 1MB),而不影响全局 maxPostSize(如 20MB)配置。
在 spring boot 应用中,可通过自定义 filter 为 `/api/data/accept` 等特定路径单独限制 post 请求体大小(如 1mb),而不影响全局 `maxpostsize`(如 20mb)配置。
Tomcat 的 maxPostSize 是 Servlet 容器级全局配置(默认 2MB,设为 -1 表示无限制),它作用于所有请求,无法按 URL 细粒度控制。若需对特定接口(如 /api/data/accept)施加更严格的请求体限制(例如仅允许 ≤1MB),推荐在应用层实现——Spring Boot 环境下最简洁、可控的方式是使用 Filter 进行前置校验。
以下是一个生产就绪的实现方案:
✅ 正确做法:基于 Content-Length 的轻量 Filter
@Component
@Order(Ordered.HIGHEST_PRECEDENCE) // 确保最早执行,避免被其他 Filter 或拦截器绕过
public class MaxPostSizePerUrlFilter implements Filter {
private static final int ONE_MB = 1_048_576; // 更精确的 1MiB(1024×1024)
private static final String TARGET_PATH = "/api/data/accept";
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (request instanceof HttpServletRequest httpReq) {
String requestURI = httpReq.getRequestURI();
int contentLength = httpReq.getContentLength();
// 仅对目标路径且 Content-Length 明确的请求校验(兼容 POST/PUT/PATCH)
if (TARGET_PATH.equals(requestURI) && contentLength > 0 && contentLength > ONE_MB) {
throw new ServletException(
String.format("Request body size (%d bytes) exceeds allowed limit of %d bytes for %s",
contentLength, ONE_MB, TARGET_PATH)
);
}
}
chain.doFilter(request, response);
}
}
? 说明:该 Filter 利用
HttpServletRequest.getContentLength()获取请求头中的Content-Length值进行快速判断。它不读取请求体,零性能开销,且完全独立于 Tomcat 配置,与spring.servlet.context-parameters.maxPostSize或server.tomcat.max-http-post-size互不干扰。
⚠️ 注意事项
-
仅适用于
Content-Length存在的场景:HTTP/1.1 普通 POST/PUT 请求通常携带该头;但分块传输(Chunked Transfer-Encoding)或某些代理转发后可能丢失该值,此时getContentLength()返回-1,本 Filter 将跳过校验(可结合InputStream.available()或流式解析增强,但会增加复杂度)。 - 不替代安全防护:此 Filter 是应用层校验,建议同时在反向代理(如 Nginx)或 API 网关层设置统一请求体上限,形成纵深防御。
-
Spring MVC 层校验补充:若需更精细控制(如区分 JSON/XML 格式或动态策略),可在
@ControllerAdvice中结合RequestBodyAdvice实现解析前拦截,但 Filter 方案已覆盖绝大多数场景。
✅ 验证方式
启动应用后,发送超限请求验证:
Filter











