在我们的应用程序中,我们使用 @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
使用ConfigurableEmbeddedServletContainer
BEAN的应用程序的例外,以返回自定义的 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
处理程序被打破了,并且该应用程序现在从上面的@ExceptionHandler
返回根据handleAllExceptions
返回所配置的自定义错误页面。<<<<<<<<<<<<
目前尚不清楚ConfigurableEmbeddedServletContainer
配置的行为是否有1.5.1以来的行为发生变化,但是配置不像以前那样工作,就像@controllerAdvice看起来像接管我们代码中的所有404处理程序的所有异常处理程序。<<<<<<<<<<<<<<<<<<<<<<<<<</p>
任何建议或指导都会有助于了解原因和解决方案/解决方法。
感谢ADV!
----编辑----
正如安迪建议的那样,请在下面找到证明问题/行为的示例项目。
应用程序类
@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"));
}
}
}
测试类
@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");
}
}
}
html模板
<!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>
最简单的验证方法是运行代码库中存在的测试用例。
要寻找的主要测试是-showPageNotFoundWhenEndPointDoesNotExist
,它解释了正在测试的行为。该测试将通过Spring Boot 1.4.4.Release版本进行运行,但是当版本升级到最新的1.5.1.Release。
要注意的另一个要点是,如果从SpringbootApplication注释类中删除extends SpringBootServletInitializer
,则测试案例将通过并且行为是预期的。这可能进一步有助于零到潜在的有问题的领域。
对于我们的完整用户酶,我们需要扩展SpringBootServletInialializer,因此问题是不可避免的。
Spring Boot 1.5.1中有一个错误,这意味着每当您子类SpringBootServletInitializer
时都会注册ErrorPageFilter
。仅当您将应用程序打包为战争并将其部署到独立容器时,才应注册。此不需要的过滤器正在破坏您的自定义错误页面配置。该错误将在1.5.2中固定。