Spring Boot REST API请求超时配置问题咨询
给Spring Boot MongoDB查询API添加请求超时的几种方案
针对你这个对外暴露MongoDB数据的REST接口,我整理了几个实用的超时实现方案,你可以根据自己的场景选择:
1. Spring MVC层面直接设置请求超时
这是最简单的方式,直接在控制器的请求映射注解里指定超时时间,到时间后Spring会自动终止请求并抛出超时异常。
修改你的控制器方法注解,加上timeout参数(单位:毫秒):
@RequestMapping(value = "/{coll}", method = RequestMethod.GET, timeout = 5000) // 5秒超时 public List<Map> retrieveMongoData(@PathVariable("collection") String collection , @RequestParam Map<String,String> requestParams) throws Exception{ Query query = new Query(); // ... 你的查询逻辑 return mongoTemplate.find(query, Map.class, collection); }
注意:这个超时是针对整个HTTP请求的生命周期,不管后端MongoDB查询是否完成,到时间就会触发超时。
2. MongoDB查询层面设置超时
如果你的超时需求主要是针对MongoDB的慢查询,可以直接在Query对象上设置查询超时,让MongoDB服务器主动终止耗时过长的查询,避免占用数据库资源。
在构建Query的时候添加maxTime配置:
@RequestMapping(value = "/{coll}", method = RequestMethod.GET) public List<Map> retrieveMongoData(@PathVariable("collection") String collection , @RequestParam Map<String,String> requestParams) throws Exception{ Query query = new Query(); // 设置查询超时为5秒 query.maxTime(5, TimeUnit.SECONDS); // ... 你的查询条件构建逻辑 return mongoTemplate.find(query, Map.class, collection); }
这种方式会让MongoDB在查询超过指定时间后抛出MongoTimeoutException,你可以在全局异常处理器里捕获这个异常,返回合适的HTTP响应(比如408 Request Timeout)。
3. 异步处理+自定义超时控制
如果需要更灵活的超时逻辑(比如超时后执行降级逻辑),可以用Spring的异步支持结合CompletableFuture来实现:
步骤1:开启异步支持
在你的Spring Boot启动类上添加@EnableAsync注解:
@SpringBootApplication @EnableAsync public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
步骤2:重构查询逻辑为异步方法
可以把MongoDB查询逻辑抽成一个异步方法:
@Service public class MongoDataService { @Autowired private MongoTemplate mongoTemplate; @Async public CompletableFuture<List<Map>> queryDataAsync(String collection, Query query) { List<Map> result = mongoTemplate.find(query, Map.class, collection); return CompletableFuture.completedFuture(result); } }
步骤3:控制器中调用异步方法并设置超时
@RequestMapping(value = "/{coll}", method = RequestMethod.GET) public List<Map> retrieveMongoData(@PathVariable("collection") String collection , @RequestParam Map<String,String> requestParams) throws Exception{ Query query = new Query(); // ... 你的查询条件构建逻辑 // 调用异步方法并设置5秒超时 CompletableFuture<List<Map>> future = mongoDataService.queryDataAsync(collection, query); try { return future.get(5, TimeUnit.SECONDS); } catch (TimeoutException e) { // 超时后的处理逻辑,比如返回空列表或自定义响应 throw new RequestTimeoutException("查询超时,请稍后重试"); } }
额外建议:全局异常处理
不管用哪种方案,建议添加全局异常处理器来统一处理超时异常,返回友好的响应:
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler({RequestTimeoutException.class, MongoTimeoutException.class}) public ResponseEntity<Map<String, String>> handleTimeoutException(Exception e) { Map<String, String> response = new HashMap<>(); response.put("code", "408"); response.put("message", e.getMessage()); return new ResponseEntity<>(response, HttpStatus.REQUEST_TIMEOUT); } }
内容的提问来源于stack exchange,提问作者Shashika




