在使用 Spring Boot
如果出现错误会出现 Whitelabel Error Page
页面,这个是 Spring Boot
默认处理错误的一个页面,是一硬编码的形式创建的。我们可以替换调,使用自己的error页面,并且美化它。
网上也有很多类似的文章,不过看了很多有的不全面、有的根本就是错误的(比如设置server.error.whitelabel.enabled=false
添加error.html
,这是有前提的), 今天我们从源码的角度来分析它并给出解决方案。
首选Spring Boot
如果出现错误,比如:500
、503
、404
等,均是有 org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController
处理的,我们也可以重写它(如果你重写了它,你会惊奇的发现:下面的内容是多余的,哈哈)实现自己的逻辑;
从图上可以看出 Spring Boot
想的很周全,同步和异步均有处理,这里我们只讨论同步的问题, 因为只有同步会出现Whitelabel Error Page
我们定位到解析视图的那句代码
ModelAndView modelAndView = resolveErrorView(request, response, status, model);
resolveErrorView
是由父类AbstractErrorControllers
实现
ErrorViewResolver
的默认实现是 DefaultErrorViewResolver
从resolve
方法中我们可以拆分一下几步
1、找到可用的模版引擎提供者
假如出现的错误是
500
则此时errorViewName="error/500"
-
查找逻辑交给了
TemplateAvailabilityProviders
类的getProvider
方法,此方法会缓存已经存在的模板引擎提供者, 具体由findProvider
去查找,若findProvider
也没找到会默认注册一个NoTemplateAvailabilityProvider
-
注意
this.providers
这是Spring Boot
在容器启动的时候就会添加的,通过模板引擎类名是否存在来判断是否添加某个的模板引擎提供者,默认Spring Boot
会注册一下几个模板引擎提供者;
-
加载模板引擎提供者
loadFactories
加载的是spring-boot-autoconfigure-2.xxxx.jar
下面的META-INF/spring.factories
, 此方法可以获取父类所有的实现类
-
这里以
ThymeleafTemplateAvailabilityProvider
为例
从图中可以看出找的是classpath:/templates/error/500.html
所以若出现500
错误我们可以在src/main/resources/
下新建目录templates/error
在新建一个thymeleaf
的500.html
模板就可以了;404
错误同理 -
从这里我们不难看出若想成功找到错误模板必须满足一下条件
- 类路径存在模板引擎的
jar
classpath
下存在存在当前错误模板(例:500.html)
2、若第1步中的provider
找到则不用继续下一步,直接返回找到的视图
3、若第1步中没有满足条件的provider
则交给resolveResource
处理;我们来看看resolveResource
的逻辑
这一步主要的直接获取静态的html
;一般500
和404