You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 18:04:39