java - 获取@RestControllerAdvice 中带注释的@Async 方法中引发的异常
问题描述
这里有一个非常相似的问题,但答案不足以解决我的问题。
我在一个@Service
类中有这个方法:
@Async
public void activateUser(...){
if(someCondition){
throw new GeneralSecurityException();
}
}
控制器:
@GetMapping( "/activate")
public ResponseEntity<Void> activate(...){
myService.activateUser(...);
}
控制器建议:
@RestControllerAdvice( basePackages = "com.app.security" )
public class SecurityAdviceController extends ResponseEntityExceptionHandler {
@ExceptionHandler( GeneralSecurityException.class )
public ResponseEntity<GeneralSecurityExceptionBody> handleGeneralSecurityException( GeneralSecurityException ex ) {
return ResponseEntity
.status( HttpStatus.MOVED_PERMANENTLY )
.header( HttpHeaders.LOCATION, ex.getUrl() )
.body( null );
}
我们到了。由于异常将在另一个线程中引发,我该如何继续使其可用于@RestControllerAdvice
?
许多人建议实施AsyncUncaughtExceptionHandler,我同意,但这并不能回答问题。
当我删除@Async
时,一切都很好,我可以看到同一个线程执行所有任务,但@Async
我有 2 个线程参与。
一种解决方案是让父线程抛出异常(但这太麻烦了,我不知道如何实现)。
谢谢你的帮助。
解决方案
如果你真的想异步工作,那么很可能你使用了错误的工具——最好切换到Spring WebFlux并使用响应式方法。
回到这个问题,我可以提出两种方法:
- 去掉
@Async
或者使用SyncTaskExecutor
,所以任务会在调用线程中同步执行。 - 摆脱
@ExceptionHandler(GeneralSecurityException.class)
这种特殊的方法。相反,使用CompletableFuture
并提供exceptionally
经过处理的逻辑。下面是CompletableFuture
在控制器和服务中使用的草图:
@Controller
public class ApiController {
private final Service service;
public ApiController(Service service) {
this.service = service;
}
@GetMapping( "/activate")
public CompletableFuture<Void> activate(...){
return service.activateUser(...)
.exceptionally(throwable -> ... exception handling goes here ...)
}
}
@Service
public class Service {
@Async
public CompletableFuture<Void> activateUser(...) {
CompletableFuture<Void> future = new CompletableFuture<>();
... your code goes here ...
if(someCondition){
future.completeExceptionally(new GeneralSecurityException());
} else {
future.complete(null);
}
return future;
}
}
推荐阅读
- android - ExoPlayer 播放视频时间过长
- db2 - 如何在没有字符分隔符或列分隔符的 Db2 中导出文件?
- javascript - 将函数值从父级传递给子级
- c++ - 在以下情况下,由于 & 运算符会发生什么?
- java - 结果集关闭后,我收到操作不允许
- marklogic - MarkLogic 10 - 托管文档在 dls:document-checkout-update-checkin 上抛出异常
- c++ - 如何定义触发计算的 const getter?
- node.js - 如何解决 NJS 错误:012,添加日期的正确方法是什么?
- javascript - 将当前浏览器的源代码存储在 chrome 扩展中
- java - react-native-facebook-login:尝试登录导致 Instrumentation.java 错误