定制应用程序错误页面
错误总是会发生的,那些在生产环境里最健壮的应用程序偶尔也会遇到麻烦。虽然减小用户遇到错误的概率很重要,但让应用程序展现一个好的错误页面也同样重要。
近年来,富有创意的错误页已经成为了一种艺术。如果你曾见到过 GitHub.com 的星球大战错误页,或者是 DropBox.com 的 Escher 立方体错误页的话,你就能明白我在说什么了。
我不知道你在使用阅读列表应用程序时有没有碰到错误,如果有的话,你看到的页面应该和图3-1里的很像。

Spring Boot 默认提供这个 “白标”(whitelabel)错误页,这是自动配置的一部分。虽然这比 Stacktrace 页面要好一点,但和网上那些伟大的错误页艺术品却不可同日而语。为了让你的应用程序故障页变成大师级作品,你需要为应用程序创建一个自定义的错误页。
Spring Boot 自动配置的默认错误处理器会查找名为 error 的视图,如果找不到就用默认的白标错误视图,如图3-1所示。因此,最简单的方法就是创建一个自定义视图,让解析出的视图名为 error。
这一点归根到底取决于错误视图解析时的视图解析器。
-
实现了 Spring 的 View 接口的 Bean,其 ID 为 error(由 Spring 的 BeanNameViewResolver 所解析)。
-
如果配置了 Thymeleaf,则有名为 error.html 的 Thymeleaf 模板。
-
如果配置了 FreeMarker,则有名为 error.ftl 的 FreeMarker 模板。
-
如果配置了 Velocity,则有名为 error.vm 的 Velocity 模板。
-
如果是用 JSP 视图,则有名为 error.jsp 的 JSP 模板。
因为我们的阅读列表应用程序使用了 Thymeleaf,所以我们要做的就是创建一个名为 error.html 的文件,把它和其他的应用程序模板一起放在模板文件夹里。代码清单3-7是一个简单有效的错误页,可以用来代替默认的白标错误页。
代码清单3-7 阅读列表应用程序的自定义错误页
<html>
<head>
<title>Oops!</title>
<link rel="stylesheet" th:href="@{/style.css}"></link>
</head>
<html>
<div class="errorPage">
<span class="oops">Oops!</span><br/>
<img th:src="@{/MissingPage.png}"></img>
<p>There seems to be a problem with the page you requested // 显示请求路径
(<span text="${path}">/readingList</span>).</p>
// 显示错误明细
<p th:text="${'Details: ' + message}"></p>
</div>
</html>
</html>
这个自定义的错误模板应该命名为 error.html,放在模板目录里,这样 Thymeleaf 模板解析器才能找到它。在典型的 Maven 或 Gradle 项目里,这就意味着要把该文件放在 src/main/resources/templates 中,运行时它就在 Classpath 的根目录里。
基本上,这个简单的 Thymeleaf 模板就是显示一张图片和一些提示错误的文字。其中有两处特别的信息需要呈现:错误的请求路径和异常消息。但这还不是错误页上的全部细节。默认情况下,Spring Boot 会为错误视图提供如下错误属性。
-
timestamp:错误发生的时间。
-
status:HTTP 状态码。
-
error:错误原因。
-
exception:异常的类名。
-
message:异常消息(如果这个错误是由异常引起的)。
-
errors:BindingResult 异常里的各种错误(如果这个错误是由异常引起的)。
-
trace:异常跟踪信息(如果这个错误是由异常引起的)。
-
path:错误发生时请求的 URL 路径。
其中某些属性,比如 path,在向用户交待问题时还是很有用的。其他的,比如 trace,用起来要保守一点,将其隐藏,或者用得聪明点,让错误页尽可能对用户友好。
请注意,模板里还引用了一张名为 MissingPage.png 的图片。图片的实际内容并不重要,所以尽情挑选适合你的图片就好了,但请一定将它放在 src/main/resources/static 或 src/main/resources/public 里,这样应用程序运行时才能找到它。
图3-2是发生错误时用户会看到的页面。虽然它算不上一件艺术品,但还是把应用程序错误页的艺术水准稍微提高了那么一点。

小结
Spring Boot 消除了 Spring 应用程序中经常要用到的很多样板式配置。让 Spring Boot 处理全部配置,你可以仰仗它来配置那些适合你的应用程序的组件。当自动配置无法满足需求时,Spring Boot 允许你覆盖并微调它提供的配置。
覆盖自动配置其实很简单,就是显式地编写那些没有 Spring Boot 时你要做的 Spring 配置。Spring Boot 的自动配置被设计为优先使用应用程序提供的配置,然后才轮到自己的自动配置。
即使自动配置合适,你仍然需要调整一些细节。Spring Boot 会开启多个属性解析器,让你通过环境变量、属性文件、YAML 文件等多种方式来设置属性,以此微调配置。这套基于属性的配置模型也能用于应用程序自己定义的组件,可以从外部配置源加载属性并注入到 Bean 里。
Spring Boot 还自动配置了一个简单的白标错误页,虽然它比异常跟踪信息友好一点,但在艺术性方面还有很大的提升空间。幸运的是,Spring Boot 提供了好几种选项来自定义或完全替换这个白标错误页,以满足应用程序的特定风格。
现在我们已经用 Spring Boot 写了一个完整的应用程序,我们会验证它能否满足预期。除了自己在浏览器里手工点点之外,我们还应该要写一些自动化、可重复运行的测试来检查这个应用程序,证明它能正确运作。这也是我们在第 4 章里要做的事。