Springboot 1.5.1升级 - MVC异常处理问题

时间:2017-02-22 06:38:17

标签: spring-boot

在我们的应用程序中,我们使用@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,因此问题是不可避免的。

1 个答案:

答案 0 :(得分:1)

Spring Boot 1.5.1中有a bug,这意味着每当您继承ErrorPageFilter时都会注册SpringBootServletInitializer。只有在将应用程序打包为战争并将其部署到独立容器时才应注册它。这个不需要的过滤器会破坏您的自定义错误页面配该错误将在1.5.2中修复。