Spring MVC如何为特定端点禁用请求超时
Spring MVC如何为特定端点禁用请求超时
当然可以针对单个端点调整请求超时,完全不用全局修改!这里有两个实用的方案,你可以根据自己的Spring版本和需求来选择:
方法一:使用WebAsyncTask包装返回值(最推荐)
这个方法最直接,只需要修改你的控制器方法,就能单独给这个端点设置超时时间,完全不影响其他接口。
你只需要把原来返回的StreamingResponseBody用WebAsyncTask包装起来,同时指定超时时间(比如设置为5分钟,或者用-1表示永不超时):
@RestController public class Controller { @PostMapping(value = "/.../endpoint", produces = "application/zip") public ResponseEntity<WebAsyncTask<StreamingResponseBody>> renderImages(...) { // 原来的StreamingResponseBody逻辑不变 StreamingResponseBody body = outputStream -> { // 你的图片渲染、写入流的逻辑 // ... }; // 设置超时时间,比如300000毫秒=5分钟,-1表示无超时 WebAsyncTask<StreamingResponseBody> asyncTask = new WebAsyncTask<>(300000L, body); // 可选:设置超时后的回调逻辑,比如返回超时响应 asyncTask.onTimeout(() -> ResponseEntity.status(HttpStatus.REQUEST_TIMEOUT).body(null)); return ResponseEntity.ok(asyncTask); } }
这个方案的好处是精准控制单个端点,代码侵入性低,不需要额外的配置类,非常适合你的场景。
方法二:通过WebMvcConfigurer全局配置路径级超时
如果你的项目中有多个需要调整超时的端点,可以用这个方法统一管理。创建一个配置类,实现WebMvcConfigurer接口,针对特定路径设置不同的超时规则:
@Configuration public class CustomAsyncTimeoutConfig implements MvcAsyncConfigurer { @Override public void configureAsyncSupport(AsyncSupportConfigurer configurer) { // 保持全局默认超时为30秒 configurer.setDefaultTimeout(30000L); // 自定义Callable拦截器,针对特定路径处理超时 configurer.registerCallableInterceptors(new TimeoutCallableProcessingInterceptor() { @Override public <T> Object handleTimeout(NativeWebRequest request, Callable<T> task) throws Exception { HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class); if (servletRequest != null && "/.../endpoint".equals(servletRequest.getRequestURI())) { // 这里可以自定义该端点的超时处理逻辑 // 如果想让它永不超时,其实方法一更直接 return super.handleTimeout(request, task); } return super.handleTimeout(request, task); } }); // 或者针对不同路径分配不同的异步任务执行器(进阶用法) configurer.setTaskExecutor(new AsyncTaskExecutor() { private final AsyncTaskExecutor defaultExecutor = new SimpleAsyncTaskExecutor(); // 为长耗时任务创建单独的执行器 private final AsyncTaskExecutor longTimeoutExecutor = new ThreadPoolTaskExecutor() {{ setCorePoolSize(5); setMaxPoolSize(10); setQueueCapacity(20); initialize(); }}; @Override public void execute(Runnable task) { defaultExecutor.execute(task); } @Override public void execute(Runnable task, long startTimeout) { defaultExecutor.execute(task, startTimeout); } @Override public Future<?> submit(Runnable task) { return defaultExecutor.submit(task); } @Override public <T> Future<T> submit(Callable<T> task) { NativeWebRequest request = RequestContextHolder.getRequestAttributes(); if (request != null) { HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class); if (servletRequest != null && "/.../endpoint".equals(servletRequest.getRequestURI())) { return longTimeoutExecutor.submit(task); } } return defaultExecutor.submit(task); } }); } }
这个方案适合批量管理多个端点的超时规则,但相对方法一来说配置更复杂一些。
为什么不推荐全局修改?
你之前在application.yaml里设置spring.mvc.async.request-timeout: -1会禁用所有端点的超时,这会带来潜在的性能和资源风险,比如恶意请求可能长时间占用服务器资源,所以针对单个端点调整才是更安全的做法。
备注:内容来源于stack exchange,提问作者Fury_Fiber
相关产品推荐
相关产品推荐

