2017-02-22 61 views
0

在我们的应用中使用@ControllerAdvice@ExceptionHandler来处理所有类型的exceptions和报告这些作为INTERNAL_SERVER_ERROR如下:Springboot 1.5.1升级 - MVC异常处理问题

@ControllerAdvice 
public class ControllerExceptionHandler { 

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 
    @ExceptionHandler(Exception.class) 
    public String handleAllExceptions() { 
     return "error"; 
    } 
} 

除此之外,我们也有处理程序照顾NOT_FOUND例外使用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处理程序被破坏,现在应用程序返回上面@ExceptionHandlerhandleAllExceptions所配置的自定义错误页面。

从1.5.1开始,配置ConfigurableEmbeddedServletContainer的行为有变化,但配置不像以前那样工作,因为@ControllerAdvice看起来像是接管了所有异常处理程序,覆盖了代码中的404处理程序。

任何建议或指导将有助于了解原因和修复/解决方法。

谢谢!

---- ----编辑

至于建议由安迪请发现证明了问题/行为的一个示例项目下面。

App类

@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,则测试用例会通过并且行为如预期。这可能会进一步帮助您解决潜在的问题领域。

对于我们的完整用例,我们需要扩展SpringBootServletInitializer,因此这个问题是不可避免的。

+0

在进一步调查中,我们删除了'@ ControllerAdvice'类和'error.html'模板文件,以查看是否允许添加的ErrorPage起作用,但是404的白标签错误页面是显示而不是自定义页面。它表明,'ConfigurableEmbeddedServletContainer' bean配置可能是未能提供所需结果的配置。 –

+0

您能否为此问题提供一个[最小,完整,可验证的示例](/ help/mcve)? –

+0

@AndyWilkinson - 完整的代码在上面的编辑部分提供。请让我知道,如果它不够。 –

回答

0

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

+0

感谢您的确认 –