在我们的应用程序中,我们使用@ControllerAdvice
和@ExceptionHandler
来处理所有类型的exceptions
并将其报告为INTERNAL_SERVER_ERROR
,如下所示:
@ControllerAdvice
public class ControllerExceptionHandler {
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(Exception.class)
public String handleAllExceptions() {
return "error";
}
}
除此之外,我们还有处理程序来处理使用NOT_FOUND
bean的应用程序的ConfigurableEmbeddedServletContainer
例外,以返回自定义的 pageNotFound 模板,如下所示:
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
registry.addViewController("/404").setViewName("pageNotFound");
}
@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return (container) -> container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,
"/404"));
}
直到SBSP 1.4.X版本一直运行良好但是由于我们将应用程序迁移到SBSP 1.5.1,NOT_FOUND
处理程序已损坏,应用程序现在按照{{返回已配置的自定义错误页面1}}来自handleAllExceptions
以上。
不清楚自1.5.1以来@ExceptionHandler
配置的行为是否发生了变化,但是配置不像以前一样工作,因为@ControllerAdvice看起来像接管所有异常处理程序一样我们代码中的404处理程序。
任何建议或指导都有助于了解原因和修复/解决方法。
先谢谢!
---- ---- EDIT
正如安迪所建议的那样,请在下面找到证明问题/行为的示例项目。
App Class
ConfigurableEmbeddedServletContainer
测试类
@SpringBootApplication
public class NotFoundApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(NotFoundApplication.class, args);
}
@Configuration
public static class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/404").setViewName("pageNotFound");
}
@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return (container) -> container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,
"/404"));
}
}
}
HTML模板
@RunWith(SpringRunner.class)
@SpringBootTest(classes = NotFoundApplication.class,
webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
public class NotFoundPageIT extends FluentTest {
private WebDriver webDriver = new HtmlUnitDriver();
@Value("${local.server.port}")
private int port;
@Page
private NotFoundPage notFoundPage;
@Override
public WebDriver getDefaultDriver() {
return webDriver;
}
@Override
public String getDefaultBaseUrl() {
return "http://localhost:" + port;
}
@Test
public void showPageNotFoundWhenEndPointDoesNotExist() throws Exception {
goTo("/notFound");
notFoundPage.isAt();
}
public static class NotFoundPage extends FluentPage {
@Override
public void isAt() {
assertThat(title()).contains("404 Page Unavailable");
assertThat(find("body").getText()).contains("The requested page is not found");
}
}
}
最简单的验证方法是运行代码库中的测试用例。
要查找的主要测试是 - <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
<meta charset="UTF-8" />
<title>404 Page Unavailable</title>
</head>
<body>
<h1>The requested page is not found</h1>
</body>
</html>
,它解释了测试中的行为。测试将通过Spring Boot 1.4.4.RELEASE版本运行,但在版本升级到最新的1.5.1.RELEASE时失败。
要注意的另一个问题是,如果从SpringBootApplication带注释的类中删除showPageNotFoundWhenEndPointDoesNotExist
,则测试用例将通过并且行为符合预期。这可能会进一步帮助归结为潜在的问题区域。
对于我们的完整用例,我们需要扩展SpringBootServletInitializer,因此问题是不可避免的。
答案 0 :(得分:1)
Spring Boot 1.5.1中有a bug,这意味着每当您继承ErrorPageFilter
时都会注册SpringBootServletInitializer
。只有在将应用程序打包为战争并将其部署到独立容器时才应注册它。这个不需要的过滤器会破坏您的自定义错误页面配该错误将在1.5.2中修复。