处理Spring @Async方法抛出的异常

twh00eeo  于 2023-11-16  发布在  Spring
关注(0)|答案(2)|浏览(205)

在我的Sping 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,全局异常处理程序将按预期调用。如何异步调用此方法,而不绕过全局异常处理程序?

dohp0rv5

dohp0rv51#

如果我理解正确的话,您希望处理异步任务,但在出现错误时,使错误处理同步并通知用户。
如果不改变你的逻辑,这似乎是不可能的定义.你做的cnrc调用,因为你不想让用户等待繁重的处理,即响应速度比繁重的进程,但你想等待,如果它的错误,你不能预见.我认为你必须改变你的方式来处理这种情况下,需要重新考虑你的逻辑.
更复杂的方法是通过WebSocket连接或从客户端到服务器的常量轮询来处理错误处理,其中错误处理程序通知用户。这意味着用户会延迟错误。
一个更简单的方法是允许用户再次运行该过程“没有邮件?再次发送邮件”或类似的东西。

ni65a41a

ni65a41a2#

根据评论,似乎我没有很好地解释这个问题。我已经测试了下面的解决方案,并对它满足我的要求感到满意

public class EmailService {

    @Async
    public CompletableFuture<?> send(String address, String subject, String body) {
        try {
            // make a HTTP call to SendGrid's API
            return CompletableFuture.completedFuture(null);
        } catch (Exception ex) {
            return CompletableFuture.failedFuture(ex);
        }
    }
}

public class PasswordService {

    @Autowired
    private EmailService emailService;

    public void resetAll(String emailAddresses) {

        var emailTasks = emailAddresses.stream()
            .map(email -> emailSendingService.send(email, "Your new password is", "open-sesame"))
            .toArray(CompletableFuture[]::new);

        // wait for all the calls to emailService to complete, throw an
        // exception if any of them fail
        CompletableFuture.allOf(emailTasks).join();
    }
}

字符串

相关问题