请求作用域 bean 异常和 @ControllerAdvice
Request scoped bean exceptions and @ControllerAdvice
我有一个自定义 Spring 引导 AutoConfiguration
class,我正在其中创建自定义 class 的 @RequestScop
ed 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>>() {
});
}
}
我有一个自定义 Spring 引导 AutoConfiguration
class,我正在其中创建自定义 class 的 @RequestScop
ed 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>>() {
});
}
}