springboot 自定义错误页面
Spring Boot默认使用嵌入式Tomcat,默认没有页面来处理404等常见错误。因此,为了给用户最佳的使用体验,404等常见错误需要我们自定义页面来处理。
在springboot2.0之前用org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer类来实现该功能。
使用Java 7内部类的实现:
@Bean public EmbeddedServletContainerCustomizer containerCustomizer() { return new EmbeddedServletContainerCustomizer() { @Override public void customize(ConfigurableEmbeddedServletContainer container) { ErrorPage error401Page = new ErrorPage(HttpStatus.UNAUTHORIZED, "/401.html"); ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html"); ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500.html"); container.addErrorPages(error401Page, error404Page, error500Page); } }; }
Java 8的lambda表达式写法:
@Bean public EmbeddedServletContainerCustomizer containerCustomizer() { return (container -> { ErrorPage error401Page = new ErrorPage(HttpStatus.UNAUTHORIZED, "/401.html"); ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html"); ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500.html"); container.addErrorPages(error401Page, error404Page, error500Page); }); }
在代码中创建了三个ErrorPage实例来处理三个通用的HTTP错误状态码,并将他们添加到container当中。ErrorPage类是一个封装了错误信息的类,它可以在Jetty和Tomcat环境下使用。
错误页面需要放在项目static内容目录下,它的默认位置是:src/main/resources/static,如下图所示:
在Spring Boot2.0以上配置嵌入式Servlet容器时EmbeddedServletContainerCustomizer类不存在,被WebServerFactoryCustomizer替代
使用WebServerFactoryCustomizer接口替换EmbeddedServletContainerCustomizer组件完成对嵌入式Servlet容器的配置,示例代码如下:
@Bean public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){
return (container -> {
ErrorPage error401Page = new ErrorPage(HttpStatus.UNAUTHORIZED, "/error/401.html");
ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404.html");
ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500.html");
container.addErrorPages(error401Page, error404Page, error500Page);
});
}
在WebServerFactoryCustomizer接口中使用ConfigurableWebServerFactory对象实现对customize()方法的转换,从而实现对嵌入式servlet容器的配置。
附注:
springboot 1.x
import org.apache.catalina.connector.Connector; import org.apache.coyote.ProtocolHandler; import org.apache.coyote.http11.Http11NioProtocol; import org.apache.tomcat.util.threads.ThreadPoolExecutor; import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.boot.web.servlet.ErrorPage; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; @Component public class EmbeddedTomcatConfig implements EmbeddedServletContainerCustomizer{ @Override public void customize(ConfigurableEmbeddedServletContainer container) { TomcatEmbeddedServletContainerFactory factory = (TomcatEmbeddedServletContainerFactory)container; factory.addConnectorCustomizers(new TomcatConnectorCustomizer() { @Override public void customize(Connector connector) { Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler(); protocol.setMaxConnections(200); protocol.setMaxThreads(200); protocol.setSelectorTimeout(3000); protocol.setSessionTimeout(3000); protocol.setConnectionTimeout(3000); } }); } }
通过实现org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer的customize方法来实现自定义
springboot 2.x
import org.apache.catalina.connector.Connector; import org.apache.coyote.ProtocolHandler; import org.apache.coyote.http11.Http11NioProtocol; import org.apache.tomcat.util.threads.ThreadPoolExecutor; import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; @Component public class EmbeddedTomcatConfig implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> { @Override public void customize(ConfigurableServletWebServerFactory factory) { ((TomcatServletWebServerFactory)factory).addConnectorCustomizers(new TomcatConnectorCustomizer() { @Override public void customize(Connector connector) { Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler(); protocol.setMaxConnections(200); protocol.setMaxThreads(200); protocol.setSelectorTimeout(3000); protocol.setSessionTimeout(3000); protocol.setConnectionTimeout(3000); } }); } }
在2.x版本改为实现org.springframework.boot.web.server.WebServerFactoryCustomizer接口的customize方法
springboot1.x的相关类如下:
- org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer
- org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer
- org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer
- org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory
springboot2.x的相关类如下:
- org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory
- org.springframework.boot.web.server.WebServerFactoryCustomizer
- org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer
- org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory