8

我有一个@ControllerAdvice类来处理来自我的 SpringMVC 控制器的异常。我想在@ExceptionHandler方法中捕获已知类型(RuntimeException)的异常,然后抛出e.getCause()异常并让同一个@ControllerAdvice 类捕获该异常。

示例代码:

@ControllerAdvice
public class ExceptionHandlingAdvice
{
    @ExceptionHandler( RuntimeException.class )
    private void handleRuntimeException( final RuntimeException e, final HttpServletResponse response ) throws Throwable
    {
        throw e.getCause(); // Can be of many types
    }

    // I want any Exception1 exception thrown by the above handler to be caught in this handler
    @ExceptionHandler( Exception1.class )
    private void handleAnException( final Exception1 e, final HttpServletResponse response ) throws Throwable
    {
        // handle exception
    }
}

这可能吗?

4

2 回答 2

1

您可以检查 RuntimeException 是否是 Exception1.class 的实例并直接调用该方法:

 private void handleRuntimeException( final RuntimeException e, final HttpServletResponse response ) throws Throwable
{
    if (e instanceof Exception1) handleAnException(e,response);
    else throw e.getCause(); // Can be of many types
}
于 2016-03-29T11:09:38.930 回答
0

晚了几年......但是在处理@Async服务时遇到了这个需求 - 当抛出异常时,它们被包裹在ExecutionException.class并希望我的控制器建议将它们引导到它们的正确处理程序,这与你所处的情况相同。

使用反射,可以收集控制器通知上的所有方法,筛选匹配的@ExceptionHandler注解,e.getCause().getClass()然后调用第一个找到的方法。

@ControllerAdvice
public class ExceptionHandlingAdvice
{
    @ExceptionHandler( RuntimeException.class )
    private void handleRuntimeException( final RuntimeException e, final HttpServletResponse response )
    {
        if (e.getCause() != null) {
            Optional<Method> method = Arrays.stream(Rest.Advice.class.getMethods())
                    .filter(m -> {
                        // Get annotation
                        ExceptionHandler annotation = m.getAnnotation(ExceptionHandler.class);
                        // Annotation exists on method and contains cause class
                        return annotation != null && Arrays.asList(annotation.value()).contains(e.getCause().getClass());
                    })
                    .findFirst();

            if (method.isPresent()) {
                try {
                    method.get().invoke(this, e.getCause(), response);
                } catch (IllegalAccessException | InvocationTargetException ex) {
                    // Heard you like exceptions on your exceptions while excepting
                    ex.printStackTrace();
                }
            }
        }
        
        // Handle if not sent to another
    }

    ... other handlers
}

没有测试void——就我个人而言,我ResponseEntity<MyStandardErrorResponse>从我的处理程序返回,所以我的调用行看起来像:

return (ResponseEntity<MyStandardErrorResponse>) method.get().invoke(this, e.getCause(), request);
于 2022-01-08T20:33:22.913 回答