Spring Boot 不显示实现自定义错误控制器的错误页面



我正在尝试根据HTTP状态代码显示自定义错误页面。我所做的是在CustomErrorController中实现 Spring 的ErrorController接口,但似乎 Spring Boot 无法识别它。

我按照本教程进行操作:https://www.baeldung.com/spring-boot-custom-error-page(第 3.1 节)。

在那里,我读到首先您需要摆脱著名的Spring的默认白标错误页面。所以我这样做了:

@SpringBootApplication(exclude = { ErrorMvcAutoConfiguration.class })
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}

这似乎有效,因为白标错误页面不再出现,但现在当发生错误时,会出现 Apache Tomcat 错误页面(包含堆栈跟踪的丑陋页面)而不是我的。

然后我只是像这样实现了我的CustomErrorController

@Controller
@RequestMapping("/error")
public class CustomErrorController implements ErrorController {
@RequestMapping
public String handleError(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (statusCode != null) {
// Specific error page
return "redirect:/error/" + statusCode;
}
// Global error page
return "error/error";
}
@Override
public String getErrorPath() {
return "/error";
}
@GetMapping("/404")
public String notFoundErrorPage() {
return "error/404";
}
// Other error codes mapping methods
}

我正在使用 Thymeleaf,我的错误视图在src/main/resources/views/error下,其中每个特定的错误页面名称都遵循建议的<error_code>.html格式,因此,例如,404 错误将关联一个404.html页面。

到目前为止,我对解决其他应用程序视图没有任何问题。实际上,我已经将 Spring 安全性配置为在发生访问被拒绝且错误页面正确显示时调用/error/403端点。

/error/500也会发生同样的情况,当发生内部服务器异常时调用,因为我也实现了以下@ControllerAdvice @ExceptionHandler方法:

@ControllerAdvice
@Log4j2
public class GlobalDefaultExceptionHandler {
@ExceptionHandler(Exception.class)
public String defaultErrorHandler(Exception exception) throws Exception {
if (AnnotationUtils.findAnnotation(exception.getClass(), ResponseStatus.class) != null) {
throw exception;
}
log.catching(exception);
return "redirect:/error/500";
}
}

因此,如果这些端点中的每一个都单独工作,为什么如果 Spring 抛出错误,为什么永远不会调用handleError方法?

谢谢。

似乎您的GlobalDefaultExceptionHandler正在预先捕获每个异常。这就是为什么handleError永远不会被召唤。

您的其他端点可以工作,因为您直接调用它们 - 正如您所描述的那样。

我建议使用@ControllerAdvice来处理特定的异常,让您的CustomErrorController实现处理所有尚未处理的异常。Spring boot 会将它们包裹在 Http Status 500 的NestedServletException中。您可以通过以下方式获得handleError内部的根本原因:

Object exception = request.getAttribute("javax.servlet.error.exception");
if (String.valueOf(exception) != null) {
log.info("Nested Exception: " + String.valueOf(exception));
}

查看这些答案,了解有关 Spring 启动中的订购和错误工作流程的更多信息:

次序

弹簧启动错误处理流程

相关内容