在我的 Spring Boot 应用程序中,我有一个通过对 SendGrid API 进行(阻止)HTTP 调用来发送电子邮件的方法。在某些情况下,我会在每个请求中多次调用此方法,因此为了减轻对请求线程的影响,我通过使用
@Async
注解来异步调用此方法。
public class EmailService {
@Async
public void send(String address, String subject, String body) {
// make a HTTP call to SendGrid's API
}
}
public class PasswordService {
@Autowired
private EmailService emailService;
public void resetAll(String emailAddresses) {
emailAddresses.forEach(email -> {
emailService.send(email, "Your new password is", "open-sesame");
});
}
}
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public void handleException(Exception ex) {
ex.printStackTrace();
}
}
这种方法的问题在于它绕过了应用程序的异常处理。如果
emailService.send
引发异常,则不会调用全局异常处理程序,因此不会向客户端返回 500 HTTP 状态。
如果我删除
@Async
,全局异常处理程序将按预期调用。 如何异步调用此方法,而不绕过全局异常处理程序?
如果我理解正确,您想要处理异步任务,但如果出现错误,请同步处理错误并通知用户。
在不改变你的逻辑的情况下,根据定义这似乎是不可能的。您进行异步调用是因为您不希望用户等待繁重的处理,即响应比繁重的处理更快,但如果出现您无法预见的错误,您希望等待。我认为你必须改变处理这种情况的方式,这需要重新思考你的逻辑。
更复杂的方法是通过 WebSocket 连接或从客户端到服务器的持续轮询来处理错误,其中错误处理程序通知用户。这意味着用户会延迟收到错误。
更简单的方法是允许用户再次运行该过程“没有邮件?再次发送邮件”或类似的内容。