请求作用域 bean 异常和 @ControllerAdvice

Request scoped bean exceptions and @ControllerAdvice

我有一个自定义 Spring 引导 AutoConfiguration class,我正在其中创建自定义 class 的 @RequestScoped bean - Foo。在同一个 AutoConfiguration class 中,我正在为我的全局异常处理程序创建一个 bean,它是一个 @ControllerAdvice。所有这些 class 都打包为 jar,并在我的其他 Spring Boot web 应用程序中用作依赖项。每当控制器方法中出现异常时,都会在我的全局异常处理程序中调用适当的异常处理程序,除非 Foo 中出现异常,抛出 BeanCreationException 并且 none调用全局异常处理程序。我尝试按照某些 SO 答案中的建议添加 @Order(Ordered.HIGHEST_PRECEDENCE),但其中 none 有效。是否可以在全局异常处理程序中处理此类请求范围的 bean 异常 - @ControllerAdvice?非常感谢。

编辑 这是我的 AutoConfiguration class。 (这是在不同的罐子里)

@Configuration
@ConditionalOnClass({FooContext.class, MyGlobalExceptionHandler.class})
public class AutoConfiguration {

    // This bean is used in a Controller
    @Order
    @RequestScope
    @Bean
    @ConditionalOnMissingBean(FooContext.class)
    public FooContext fooContext() throws IOException {
        // generateFooContext() throws the exception and Spring wraps it with BeanCreationException.
        return FooContextFactory.generateFooContext(); 
    }

    @Bean
    @ConditionalOnMissingBean
    public MyGlobalExceptionHandler globalExceptionHandler(MyErrorHelper errorHelper) {
        return new MyGlobalExceptionHandler (errorHelper);
    }
}

这是MyGlobalExceptionHandler(这是在不同的罐子里)

@ControllerAdvice
@RefreshScope
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MyGlobalExceptionHandler {

    // Never invoked 
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> render(Exception ex) {
        log.error("Exception occurred: ", ex);
        return errorHelper.throwErrorException(DEFAULT_ERROR_CODE, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    /// ... 
}

我通过注册 AbstractHandlerExceptionResolver

设法解决了这个问题
@Component
public class ResponseExceptionResolver extends AbstractHandlerExceptionResolver {

    @SneakyThrows
    @Override
    protected ModelAndView doResolveException(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler,
            Exception ex
    ) {
        return handleException(request, response);
    }

    private ModelAndView handleException(
            HttpServletRequest request,
            HttpServletResponse response
    ) {
        response.setHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE);

        ErrorResponse errorResponse = ...
        return new ModelAndView(new MappingJackson2JsonView(), this.getErrorResponse(errorResponse));
    }

    private Map<String, String> getErrorResponse(ErrorResponse errorResponse) {
        return new ObjectMapper().convertValue(errorResponse, new TypeReference<Map<String, String>>() {
        });
    }
}