springboot 自定义错误页面

2022-02-10 10:07:07 浏览数 (1)

Spring Boot 默认使用嵌入式 Tomcat,默认没有页面来处理404等常见错误。因此,为了给用户最佳的使用体验,404等常见错误需要我们自定义页面来处理。

在 springboot 2.0 之前用

代码语言:javascript复制
org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer

类来实现该功能。

使用 Java7 内部类的实现:

代码语言:javascript复制
@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);
        }
    };
}

Java8 的 lambda 表达式写法:

代码语言:javascript复制
@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容器的配置,示例代码如下:

代码语言:javascript复制
@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
代码语言:javascript复制
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
代码语言:javascript复制
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 相关类如下:

代码语言:javascript复制
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 相关类如下:

代码语言:javascript复制
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

0 人点赞