Spring MVC 如何允许在Sping Boot 中仅在请求首先是HTML时使用500.html

iyzzxitl  于 8个月前  发布在  Spring
关注(0)|答案(1)|浏览(65)

我想要的是给定curl localhost:8080/fail,我希望它显示JSON异常消息,因为它是典型的API调用,但如果我从浏览器查看http://localhost:8080,我希望它显示存储在模板中的HTML版本
我目前有一个用于REST API调用的通用异常处理程序

@ControllerAdvice
public class GeneralExceptionHandler implements Ordered {

  @Override
  public int getOrder() {

    return Ordered.LOWEST_PRECEDENCE; // I'm already at lowest precedence.

  }

  @ExceptionHandler(Throwable.class)
  public ResponseEntity<Status> handleException(@NotNull Throwable e) {
    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
        .body(StatusProto.fromThrowable(e));
  }
}

但我也有一个HTML 500错误页面在src/main/templates/error/500.html我也有一个404错误页面src/main/templates/error/404.html和正确的工作。
然而,当我遇到失败时,它似乎一直在使用我的异常处理程序,即使我从浏览器访问页面。
我通过在我的控制器类中添加

@Controller // I'm not a RestController
public class MyController {

  @GetMapping("/fail")
  public String fail() {

    throw new IllegalStateException("Test for 500");

  }
}

请求/fail,但它总是给我JSON而不是HTML。
我还需要做其他配置吗?

bn31dyow

bn31dyow1#

我基本上不得不检查它是否是一个HTML请求和相应的路由

@ControllerAdvice
public class GeneralExceptionHandler implements Ordered {

  @Override
  public int getOrder() {
    return Ordered.LOWEST_PRECEDENCE;
  }

  @ExceptionHandler(Throwable.class)
  public Object handleException(@NotNull Throwable e, @NotNull final WebRequest request) {

    final var acceptHeader = request.getHeader(HttpHeaders.ACCEPT);
    var isHtmlRequest = false;
    if (acceptHeader != null) {
      isHtmlRequest = Arrays.asList(acceptHeader.split(",")).contains(MediaType.TEXT_HTML_VALUE);
    }
    if (isHtmlRequest) {
      return "error/500";
    } else {
      return ResponseEntity.internalServerError()
          .body(
              StatusProto.fromThrowable(
                  io.grpc.Status.INTERNAL
                      .withDescription(e.getMessage())
                      .withCause(e)
                      .asRuntimeException()));
    }
  }
}

解析器链中似乎也存在一个错误/不一致,因为它指出
null如果异常仍然未解决,供后续解析器尝试,如果异常仍然在最后,则允许它冒泡到Servlet容器。
但是返回null而不是error/500给了我一个0字节的内容。

相关问题