SpringBoot 2.0 之错误页面配置

1. 默认配置

1.1 配置

根据错误码匹配,如下:

目录访问优先级目录配置
classpath:/META-INF/resources/最高/error/404.html 或 /error/4xx.html
classpath:/resources/-/error/404.html 或 /error/4xx.html
classpath:/static/-/error/404.html 或 /error/4xx.html
classpath:/public/-/error/404.html 或 /error/4xx.html

2.2 调试过程:

  1. 在application.yml 里面将日志级别调为debug
logging:
  level.org: DEBUG
  1. 访问一个不存在的资源

    系统会打印如下日志:

    : getResource(META-INF/resources/error/404.html)
  --> Resource not found, returning null
    : getResource(resources/error/404.html)
  --> Resource not found, returning null
    : getResource(static/error/404.html)
  --> Resource not found, returning null
    : getResource(public/error/404.html)
  --> Resource not found, returning null
   : getResource(META-INF/resources/error/4xx.html)
   --> Resource not found, returning null
   : getResource(resources/error/4xx.html)
   :   --> Resource not found, returning null
   : getResource(static/error/4xx.html)
   :   --> Resource not found, returning null
   : getResource(public/error/4xx.html)
   : getResourceAsStream(public/error/4xx.html)
   : Exiting from "ERROR" dispatch, status 404
  1. 详细日志:
2020-09-14 18:00:28.679 DEBUG 6720 --- [nio-8080-exec-8] o.a.t.util.http.Rfc6265CookieProcessor   : Cookies: Parsing b[]: JSESSIONID=3768F0D323A90FB70F40609ECF80E636
2020-09-14 18:00:28.680 DEBUG 6720 --- [nio-8080-exec-8] o.a.catalina.connector.CoyoteAdapter     :  Requested cookie session id is 3768F0D323A90FB70F40609ECF80E636
2020-09-14 18:00:28.680 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.authenticator.AuthenticatorBase    : Security checking request GET /index5.html
2020-09-14 18:00:28.681 DEBUG 6720 --- [nio-8080-exec-8] org.apache.catalina.realm.RealmBase      :   No applicable constraints defined
2020-09-14 18:00:28.681 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.authenticator.AuthenticatorBase    : Not subject to any constraint
2020-09-14 18:00:28.682 DEBUG 6720 --- [nio-8080-exec-8] org.apache.tomcat.util.http.Parameters   : Set encoding to UTF-8
2020-09-14 18:00:28.682 DEBUG 6720 --- [nio-8080-exec-8] o.s.web.servlet.DispatcherServlet        : GET "/index5.html", parameters={}
2020-09-14 18:00:28.685 DEBUG 6720 --- [nio-8080-exec-8] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler ["classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/", "/"]
2020-09-14 18:00:28.691 DEBUG 6720 --- [nio-8080-exec-8] o.s.w.s.r.ResourceHttpRequestHandler     : Resource not found
2020-09-14 18:00:28.691 DEBUG 6720 --- [nio-8080-exec-8] o.s.web.servlet.DispatcherServlet        : Completed 404 NOT_FOUND
2020-09-14 18:00:28.693 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.c.C.[Tomcat].[localhost]           : Processing ErrorPage[errorCode=0, location=/error]
2020-09-14 18:00:28.698 DEBUG 6720 --- [nio-8080-exec-8] o.s.web.servlet.DispatcherServlet        : "ERROR" dispatch for GET "/error", parameters={}
2020-09-14 18:00:28.700 DEBUG 6720 --- [nio-8080-exec-8] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#errorHtml(HttpServletRequest, HttpServletResponse)
2020-09-14 18:00:28.723 DEBUG 6720 --- [nio-8080-exec-8] o.s.c.e.PropertySourcesPropertyResolver  : Found key 'spring.template.provider.cache' in PropertySource 'configurationProperties' with value of type String
2020-09-14 18:00:28.725 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(freemarker.template.Configuration)
2020-09-14 18:00:28.728 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.728 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(freemarker.template$Configuration)
2020-09-14 18:00:28.731 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.731 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(com.samskivert.mustache.Template)
2020-09-14 18:00:28.732 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.733 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(com.samskivert.mustache$Template)
2020-09-14 18:00:28.735 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.735 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(groovy.text.TemplateEngine)
2020-09-14 18:00:28.735 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.736 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(groovy.text$TemplateEngine)
2020-09-14 18:00:28.738 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.738 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(org.thymeleaf.spring5.SpringTemplateEngine)
2020-09-14 18:00:28.743 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.744 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(org.thymeleaf.spring5$SpringTemplateEngine)
2020-09-14 18:00:28.746 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.746 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(org.apache.jasper.compiler.JspConfig)
2020-09-14 18:00:28.748 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.749 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(org.apache.jasper.compiler$JspConfig)
2020-09-14 18:00:28.750 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.750 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       : getResource(META-INF/resources/error/404.html)
2020-09-14 18:00:28.751 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   Delegating to parent classloader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@2e0c56f1
2020-09-14 18:00:28.751 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   --> Resource not found, returning null
2020-09-14 18:00:28.751 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       : getResource(resources/error/404.html)
2020-09-14 18:00:28.751 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   Delegating to parent classloader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@2e0c56f1
2020-09-14 18:00:28.751 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   --> Resource not found, returning null
2020-09-14 18:00:28.752 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       : getResource(static/error/404.html)
2020-09-14 18:00:28.752 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   Delegating to parent classloader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@2e0c56f1
2020-09-14 18:00:28.752 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   --> Resource not found, returning null
2020-09-14 18:00:28.752 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       : getResource(public/error/404.html)
2020-09-14 18:00:28.752 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   Delegating to parent classloader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@2e0c56f1
2020-09-14 18:00:28.752 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   --> Resource not found, returning null
2020-09-14 18:00:28.753 DEBUG 6720 --- [nio-8080-exec-8] o.s.c.e.PropertySourcesPropertyResolver  : Found key 'spring.template.provider.cache' in PropertySource 'configurationProperties' with value of type String
2020-09-14 18:00:28.753 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(freemarker.template.Configuration)
2020-09-14 18:00:28.753 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.754 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(freemarker.template$Configuration)
2020-09-14 18:00:28.754 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.756 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(com.samskivert.mustache.Template)
2020-09-14 18:00:28.758 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.758 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(com.samskivert.mustache$Template)
2020-09-14 18:00:28.759 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.760 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(groovy.text.TemplateEngine)
2020-09-14 18:00:28.760 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.762 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(groovy.text$TemplateEngine)
2020-09-14 18:00:28.762 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.762 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(org.thymeleaf.spring5.SpringTemplateEngine)
2020-09-14 18:00:28.763 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.764 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(org.thymeleaf.spring5$SpringTemplateEngine)
2020-09-14 18:00:28.764 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.764 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(org.apache.jasper.compiler.JspConfig)
2020-09-14 18:00:28.765 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.765 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     findClass(org.apache.jasper.compiler$JspConfig)
2020-09-14 18:00:28.765 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2020-09-14 18:00:28.765 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       : getResource(META-INF/resources/error/4xx.html)
2020-09-14 18:00:28.766 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   Delegating to parent classloader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@2e0c56f1
2020-09-14 18:00:28.766 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   --> Resource not found, returning null
2020-09-14 18:00:28.766 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       : getResource(resources/error/4xx.html)
2020-09-14 18:00:28.766 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   Delegating to parent classloader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@2e0c56f1
2020-09-14 18:00:28.767 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   --> Resource not found, returning null
2020-09-14 18:00:28.767 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       : getResource(static/error/4xx.html)
2020-09-14 18:00:28.767 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   Delegating to parent classloader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@2e0c56f1
2020-09-14 18:00:28.767 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   --> Resource not found, returning null
2020-09-14 18:00:28.767 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       : getResource(public/error/4xx.html)
2020-09-14 18:00:28.767 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   Delegating to parent classloader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@2e0c56f1
2020-09-14 18:00:28.768 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   --> Returning 'file:/E:/%e5%ad%a6%e4%b9%a0%e8%b5%84%e6%96%99/vue/workspace/spring-boot-study/spring-boot-resources-study/target/classes/public/error/4xx.html'
2020-09-14 18:00:28.773 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       : getResourceAsStream(public/error/4xx.html)
2020-09-14 18:00:28.773 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   Delegating to parent classloader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@2e0c56f1
2020-09-14 18:00:28.774 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.loader.WebappClassLoaderBase       :   --> Returning stream from parent
2020-09-14 18:00:28.777 DEBUG 6720 --- [nio-8080-exec-8] o.s.web.servlet.DispatcherServlet        : Exiting from "ERROR" dispatch, status 404
2020-09-14 18:00:28.778 DEBUG 6720 --- [nio-8080-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet]    :  Disabling the response for further output

2. 自定义配置

2.1 源码解读

org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
  1. 错误页面配置

从源码分析,默认会调用 StaticView defaultErrorView = new StaticView();

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "server.error.whitelabel", name = "enabled", matchIfMissing = true)
	@Conditional(ErrorTemplateMissingCondition.class)
	protected static class WhitelabelErrorViewConfiguration {

		private final StaticView defaultErrorView = new StaticView();

		@Bean(name = "error")
		@ConditionalOnMissingBean(name = "error")
		public View defaultErrorView() {
			return this.defaultErrorView;
		}

		// If the user adds @EnableWebMvc then the bean name view resolver from
		// WebMvcAutoConfiguration disappears, so add it back in to avoid disappointment.
		@Bean
		@ConditionalOnMissingBean
		public BeanNameViewResolver beanNameViewResolver() {
			BeanNameViewResolver resolver = new BeanNameViewResolver();
			resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
			return resolver;
		}

	}
  1. StaticView 代码
	/**
	 * Simple {@link View} implementation that writes a default HTML error page.
	 */
	private static class StaticView implements View {

		private static final MediaType TEXT_HTML_UTF8 = new MediaType("text", "html", StandardCharsets.UTF_8);

		private static final Log logger = LogFactory.getLog(StaticView.class);

		@Override
		public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
				throws Exception {
			if (response.isCommitted()) {
				String message = getMessage(model);
				logger.error(message);
				return;
			}
			response.setContentType(TEXT_HTML_UTF8.toString());
			StringBuilder builder = new StringBuilder();
			Date timestamp = (Date) model.get("timestamp");
			Object message = model.get("message");
			Object trace = model.get("trace");
			if (response.getContentType() == null) {
				response.setContentType(getContentType());
			}
			builder.append("<html><body><h1>Whitelabel Error Page</h1>").append(
					"<p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>")
					.append("<div id='created'>").append(timestamp).append("</div>")
					.append("<div>There was an unexpected error (type=").append(htmlEscape(model.get("error")))
					.append(", status=").append(htmlEscape(model.get("status"))).append(").</div>");
			if (message != null) {
				builder.append("<div>").append(htmlEscape(message)).append("</div>");
			}
			if (trace != null) {
				builder.append("<div style='white-space:pre-wrap;'>").append(htmlEscape(trace)).append("</div>");
			}
			builder.append("</body></html>");
			response.getWriter().append(builder.toString());
		}

		private String htmlEscape(Object input) {
			return (input != null) ? HtmlUtils.htmlEscape(input.toString()) : null;
		}

		private String getMessage(Map<String, ?> model) {
			Object path = model.get("path");
			String message = "Cannot render error page for request [" + path + "]";
			if (model.get("message") != null) {
				message += " and exception [" + model.get("message") + "]";
			}
			message += " as the response has already been committed.";
			message += " As a result, the response may have the wrong status code.";
			return message;
		}

		@Override
		public String getContentType() {
			return "text/html";
		}

	}

2.2 配置

根据上面源码分析,只要自己只要自定义一个View覆盖源码中的View即可,具体操作如下:

  1. 在application.yml中配置

      server.error.whitelabel.enable = true  #默认为true
    
  2. 自定义View

 public class GlobalErrorView implements View {

    @Override
    public String getContentType() {
        return MediaType.TEXT_HTML_VALUE;
    }

    @Override
    public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        request.getRequestDispatcher("/error.html").forward(request,response);
    }

}
  1. 覆盖原来的View
@Configuration
public class GlobalErrorConfig {

    @Bean("error")
    public View error() {
        return new GlobalErrorView();
    }
}
  1. 启动服务后就会发现,原来的访问的“Whitelabel Error Page”配置页面,已经变成了自己定义的页面。

注意:
系统默认会找 /error/404.html ,没有找到会跳转到 error

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未来之道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值