首页 > 解决方案 > 在 Spring Boot 中处理异常的方法。抛出异常捕获并抛出相同的异常,这是一种不好的做法吗?

问题描述

我正在使用spring boot,并且正在处理一种处理异常的好方法:

我有这种与存储库交互以获取产品的案例。但是如果数据库存在连接问题怎么办,我不会捕捉到那个异常

Product product = productRepository.findById(productId)
                .orElseThrow(() -> new NotFoundException("Could not find a product"));
try {
// Product logic
} catch(Exception e) {
            throw new ProductException(String.format("Error getting product productId=%s. Exception message: %s",
                    productId, e.getMessage()), e);
        }

我有一个控制器建议来捕获异常并返回一个很好的响应:

@ControllerAdvice
public class ExceptionHandler extends ResponseEntityExceptionHandler {
    @ExceptionHandler({NotFoundException.class})
    public ResponseEntity<Error> handleNotFoundException(HttpServletRequest request, Exception exception) {
    .....
}

我想我可以做这样的事情:

    try {
        Product product = productRepository.findById(productId)
                    .orElseThrow(() -> new NotFoundException("Could not find a product"));
    } catch(NotFoundException e) {
        throw new NotFoundException(e.getMessage())
    } catch(Exception e) {
                throw new ProductException(String.format("Error getting product productId=%s. Exception message: %s",
                        productId, e.getMessage()), e);

这行得通,但看起来很奇怪,因为我两次抛出 NotFoundException。任何想法?

标签: javaspringjpaexceptioncontroller-advice

解决方案


一般来说,捕获一个异常并在之后再次抛出它并没有什么奇怪的。例如,您可以捕获它以将其记录在某处,然后将其扔给下一个处理程序进行实际处理(就像您的情况一样)。

你可以简单地写:

catch (NotFoundException e) {
    // Log if needed
    throw e; // <-- no need to build a new one
}

但是,对于后面的部分,捕获泛型Exception通常是一种不好的做法。这个异常可能来自太多的来源,你不能仅仅假设它是因为数据库没有响应。

所以最好的办法是你的函数捕获它知道如何处理的东西,并抛出它不知道如何处理的东西。例如:

public void yourFunction() throws NotFoundException, ProductException {
    //you don't know how to handle NotFoundException and ProductException here, hence you throw them up
    try {
        // your logic
    } catch (SpecificExceptionYouWantToCatch e) {
        //handle specific exception you know how to handle
    } catch (AnotherSpecificException e) {
        //handle other specific exception you know how to handle
    }
    //Let all the other Runtime exceptions flow up to the caller. 
}

如果出现异常,则出现问题。你不能只是包装它并假装它是一个ProductException,所以:

  • 如果您识别出异常并知道如何处理它,那么就这样做(就像您正在做的那样NotFoundException
  • 但是,如果您没有预料到该异常,那么最好让它流动。在某些时候,它可能会被捕获和处理,或者可能只会使程序崩溃。但是你会想知道它,而如果你只是把它包装成一个ProductException你可能会向系统隐藏一个更大的问题。

推荐阅读