【问题标题】:Springboot error handling HttpServerErrorException, /error, etcSpring Boot错误处理HttpServerErrorException、/error等
【发布时间】:2021-12-16 18:36:02
【问题描述】:

我在获得完整的错误处理解决方案时遇到了一些麻烦。我创建了一个捕获异常和QueryTimeException 的@ControllerAdvice 类。但是,404 Not Found 消息不会转到我的自定义页面。并且 HttpStatus.GATEWAY_TIMEOUT 没有正确路由。但是,HttpStatus.REQUEST_TIMEOUT 和异常确实可以正确路由。

这是我的错误控制器。我错过了什么或做错了什么?

@ControllerAdvice
public class MyErrorController implements ErrorController {

    public static final Logger logger = LoggerFactory.getLogger(MyErrorController.class);

    @ExceptionHandler(HttpServerErrorException.GatewayTimeout.class)
    @ResponseStatus(HttpStatus.GATEWAY_TIMEOUT)
    public String gatewayTimeout() {
        return "errors/error-timeout";
    }

    @ExceptionHandler(QueryTimeoutException.class)
    @ResponseStatus(HttpStatus.REQUEST_TIMEOUT)
    public String requestTimeout() {
        return "errors/error-timeout";
    }

    @ExceptionHandler(value = {HttpClientErrorException.class, Exception.class})
    public String handleExceptions() {
        return  "errors/error";
    }

    @RequestMapping("/error")
    public String handleErrors(HttpServletRequest request, Exception ex) {
        return  "errors/error";
    }

    // This method is deprecated, so do not add the @Override annotation
    // However, the method must remain while the Spring team has not yet removed it from the ErrorController interface
    public String getErrorPath() {
        return "/error";
    }

}

我在 application.properties 中添加了以下内容:

server.error.whitelabel.enabled=true
server.error.path=/error

为了测试上述内容,我在控制器中添加了以下方法。

    @GetMapping("/throw504")
    public ResponseEntity<Void> throwGatewayTimeout() {
        throw new HttpServerErrorException(HttpStatus.GATEWAY_TIMEOUT);
    }

    @GetMapping("/throw408")
    public ResponseEntity<Void> throwResponseTimeout() {
        throw new QueryTimeoutException();
    }

    @GetMapping("/throw500")
    public ResponseEntity<Void> throwNotImplemented() {
        throw new HttpServerErrorException(HttpStatus.NOT_IMPLEMENTED);
    }

所以我通过运行我的应用程序进行测试,导航到 localhost:8080/throw408(我得到错误超时页面)、localhost:8080/throw500(我得到错误页面),这两个都是正确的。

然后我测试 localhost:8080/throw504 错误地打开错误页面,而不是我预期的错误超时。然后我测试 localhost:8080/jskld,它显示一个通用的 404 页面,而不是我预期的错误页面。

【问题讨论】:

  • 请同时添加您对HttpStatus.NOT_IMPLEMENTED 的异常处理程序,因为您说它已经工作了
  • 你检查过我下面的答案了吗?

标签: java spring spring-boot


【解决方案1】:

让我们再分析一下,你可能会在代码中看到错误。

 @ExceptionHandler(HttpServerErrorException.GatewayTimeout.class)
    @ResponseStatus(HttpStatus.GATEWAY_TIMEOUT)
    public String gatewayTimeout() {
        return "errors/error-timeout";
    }

异常处理程序等待GatewayTimeout.class 的实例来处理此异常。

当您在控制器中创建此异常时

@GetMapping("/throw504")
    public ResponseEntity<Void> throwGatewayTimeout() {
        throw new HttpServerErrorException(HttpStatus.GATEWAY_TIMEOUT); <------
    }

如果你检查这个类,你会发现

public class HttpServerErrorException extends HttpStatusCodeException {
    private static final long serialVersionUID = -2915754006618138282L;

    public HttpServerErrorException(HttpStatus statusCode) {
        super(statusCode);
    }

所以你使用的构造函数返回一个HttpServerErrorException.class

不是GatewayTimeout.class

GatewayTimeout.class 是一个静态嵌套类,它扩展了HttpServerErrorException.class

public static final class GatewayTimeout extends HttpServerErrorException {
        private GatewayTimeout(String statusText, HttpHeaders headers, byte[] body, @Nullable Charset charset) {
            super(HttpStatus.GATEWAY_TIMEOUT, statusText, headers, body, charset);
        }

如果你仔细观察HttpServerErrorException.class,会有一个构造函数创建GatewayTimeout.class 的实例

一种方法是使用构造函数

HttpServerErrorException.create(HttpStatus.GATEWAY_TIMEOUT,"status text", new HttpHeaders(), new byte[] {}, Charset.defaultCharset());

这将返回一个 GatewayTimeout.class 的异常实例,spring 可能会匹配该实例。

所以你的控制器必须适应

  @GetMapping("/throw504")
  public ResponseEntity<Void> throwGatewayTimeout() {
    throw HttpServerErrorException.create(HttpStatus.GATEWAY_TIMEOUT,"status text", new HttpHeaders(), new byte[] {}, Charset.defaultCharset());
   }

最后,GatewayTimeout.class 是从 HttpServerErrorException 扩展而来的。所以这意味着GatewayTimeout.classHttpServerErrorException,但HttpServerErrorException 不一定是GatewayTimeout.class

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-13
    • 1970-01-01
    • 2017-08-23
    • 2022-06-17
    • 2021-01-12
    • 2020-10-08
    • 2019-05-06
    • 2016-03-22
    相关资源
    最近更新 更多