Java 为Spring引导控制器调用的特定方法设置超时
我在我的SpringBootAPI中有这个路由,它应该接收一个注册表对象,尝试将它保存到DB并通知它是否成功。这是我的控制器的方法:Java 为Spring引导控制器调用的特定方法设置超时,java,spring-boot,Java,Spring Boot,我在我的SpringBootAPI中有这个路由,它应该接收一个注册表对象,尝试将它保存到DB并通知它是否成功。这是我的控制器的方法: @POST @Path( "/save" ) public Response save( @RequestBody Registry registry ) { Response validatedResponse = validateRegistry( registry ); if ( isErrorResponse( va
@POST
@Path( "/save" )
public Response save( @RequestBody Registry registry ) {
Response validatedResponse = validateRegistry( registry );
if ( isErrorResponse( validatedResponse ) )
return validatedResponse;
try {
return ResponseBuilder.success( this.registryRepository.save( registry ) );
} catch ( Exception e ) {
LOGGER.error( "Error while trying to save", e );
return ResponseBuilder.failure( "error at /save" );
}
}
validateRegistry
如下所示:
private Response validateRegistry( Registry registry ) {
// some trivial validation on the Registry object's fields
Optional< Connection > connection;
try {
connection = connectionService.findById( registry.getConnectionIdentifier() );
registryService.setConnection( connection.get() );
try {
return registryService.doesRegistryExists( registry );
} catch ( Exception e ) {
LOGGER.failure( "error at /save (validation)" );
LOGGER.failure( e.getMessage() );
}
} catch ( Exception e ) {
return ResponseBuilder.failure( "not able to retrieve connection for given registry ");
}
return ResponseBuilder.success();
}
private Response validateRegistry(注册表){
//注册表对象字段上的一些琐碎验证
可选<连接>连接;
试一试{
connection=connectionService.findById(registry.getConnectionIdentifier());
registryService.setConnection(connection.get());
试一试{
返回registryService.doesRegistryExists(注册表);
}捕获(例外e){
LOGGER.failure(“保存(验证)时出错”);
LOGGER.failure(如getMessage());
}
}捕获(例外e){
返回ResponseBuilder.failure(“无法检索给定注册表的连接”);
}
返回ResponseBuilder.success();
}
验证的一部分包括验证是否存在相同的注册表,如您所见,我从调用方检索连接以访问其基础并搜索注册表-这就是registryService.doesRegistryExists
所做的。现在,我想将执行doesRegistryExists
的时间限制在几秒钟之内,因为有时执行查询需要花费太多的时间-中止执行是可以的,因为我可以返回一个描述情况的响应并要求稍后再试
我该怎么办?我曾尝试使用ExecutorService包装查询调用方,但它会导致调用方抛出NullPointerException。使用
ExecutorService
是一个很好的解决方案,您可以通过提交并等待一定时间的结果来获得
private ExecutorService executorService = Executors.newFixedThreadPool(10);
private Response validateRegistry( Registry registry ) {
...
try {
Callable<Response> task = () -> registryService.doesRegistryExists(registry);
Future<Response> future = executorService.submit(task);
// wait for the result for at most 2 seconds
return future.get(2, TimeUnit.SECONDS);
} catch (TimeoutException e) {
// handle the timeout exception here
} catch (Exception e) {
// handle the other exceptions here
}
...
}
private ExecutorService ExecutorService=Executors.newFixedThreadPool(10);
专用响应验证注册表(注册表){
...
试一试{
可调用任务=()->registryService.doesRegistryExists(注册表);
Future=executorService.submit(任务);
//等待结果最多2秒钟
返回future.get(2,TimeUnit.SECONDS);
}捕获(超时异常e){
//在这里处理超时异常
}捕获(例外e){
//在这里处理其他异常
}
...
}
如果连接和数据库都有超时,那么将连接本身设置为超时,而不是将其包装到另一个项目中是有意义的。另外,因为您使用的是spring boot,所以您可以使用@Transactional(timeout=5)的注释来设置5秒的超时时间,这也是有道理的,但不幸的是,我无法更改连接类,只是尝试了@Transactional(timeout=5)注释,但是,当查询执行器或其调用者在可调用的内部执行时,它抛出一个NullPointerExceptionNullPointerException
的原因是什么?它只说“java.lang.Exception:java.lang.NullPointerException”,没有堆栈跟踪