【问题标题】:Bean creation errors for request-scoped beans请求范围 bean 的 bean 创建错误
【发布时间】:2019-12-01 19:39:34
【问题描述】:

当一个 Spring bean 被注解为SCOPE_REQUEST 时,它会在 servlet 每次接收到 HTTP 请求时被创建和销毁。如果此 bean 创建失败,则会将服务器错误发送回调用方。

在这个简单的示例中,MyInputs bean 的创建取决于 HTTP 请求的内容。

@Configuration
class ApplicationConfiguration {

    @Bean
    @Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public MyInputs myInputs(HttpServletRequest request) {

        String header1 = request.getHeader("header1");
        if (header1 == null) {
            throw new MyException("header1 is missing");
        }
        return new MyInputs(header1);
    }
}

如果 HTTP 请求不包含必需的标头,则会抛出 BeanCreationException。这被翻译成无用的“500 Internal Server Error”响应。

我想返回一个对用户更友好的响应代码和正文,例如,带有有用消息的“400 Bad Request”。如何自定义此响应翻译?我找不到任何允许这样做的生命周期钩子。


注意:这是请求范围 bean 的使用方式:

@RestController
public class MyController {

    private final Provider<MyInputs> myInputsProvider;

    @Autowired
    public MyController(Provider<MyInputs> myInputsProvider) {

        this.myInputsProvider = myInputsProvider;
    }

    @GetMapping("/do-stuff")
    public void doStuff() {

        // Get the inputs for the current request
        MyInputs myInputs = myInputsProvider.get();

        // ...
    }
}

【问题讨论】:

  • 只需使用响应状态注释您的异常,如下所示:baeldung.com/spring-response-status-exception
  • @beatrice 我确实尝试过.. 问题是 Spring 将所有内容包装到 BeanCreationException 中,因此通常的处理程序不会被触发。
  • 请说明您如何尝试在请求处理程序中使用 MyInputs bean。
  • 也许使用一个拦截器来调用MyInput.setHeader 在检查它是否存在抛出异常之后。这个例外不会被春天包裹起来。看到这样的 @Bean 函数,我会感到非常惊讶 - bean 构造通常并不例外
  • @SotiriosDelimanolis 添加了一个示例。

标签: java spring rest spring-boot spring-mvc


【解决方案1】:

你可以使用@ControllerAdvice注解来处理被抛出的异常。

您还需要使用@ExceptionHandler 来处理异常。

@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MyException.class)
    public final ResponseEntity<CustomError> handleException(MyException ex, WebRequest request) {
        CustomError error = new CustomError();            
        error.setMessage(ex.getMessage());
        error.setStatus(HttpStatus.BAD_REQUEST);
        return new ResponseEntity<>(error, null, HttpStatus.BAD_REQUEST);
    }
}

【讨论】:

  • Spring 生命周期将所有内容包装到 BeanCreationException 中。我还没有看到在这种情况下触发异常处理程序,无论是使用@ExceptionHandler(BeanCreationException.class) 还是使用@ExceptionHandler(MyException.class)
  • 尝试使用@Order(Ordered.HIGHEST_PRECEDENCE) :) 如果您在请求上下文中,那么它应该可以工作。
猜你喜欢
  • 2017-09-06
  • 2013-01-21
  • 2011-11-11
  • 2012-05-26
  • 2019-12-10
  • 2012-02-24
  • 2011-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多