SpringBoot——定制错误页面及原理
更多内容,前往 IT-BLOG
一、SpringBoot 默认的错误处理机制
【1】浏览器返回的默认错误页面如下:

☞ 浏览器发送请求的请求头信息如下:text/html 会在后面的源码分析中说到。

【2】如果是其他客户端,默认则响应错误的 JSON字符串,如下所示:

☞ 其他客户端发送请求的请求头信息如下: " */* " 源码中解释。

二、原理分析
参照 ErrorMvcAutoConfiguration类:错误处理的自动配置类,以下4项为此类的重要信息。
【1】ErrorMvcAutoConfiguration.ErrorPageCustomizer:当系统出现 4xx或者 5xx之类的错误时,ErrorPageCustomizer就会生效(定制错误的响应规则),根据如下源码可知,将会来到 /error请求。
1 @Bean
2 public ErrorMvcAutoConfiguration.ErrorPageCustomizer errorPageCustomizer() {
3 return new ErrorMvcAutoConfiguration.ErrorPageCustomizer(this.serverProperties);
4 }
5
6 //进入ErrorPageCustomizer方法,发现registerErrorPages方法:注册一个错误也
7 private static class ErrorPageCustomizer implements ErrorPageRegistrar, Ordered {
8 private final ServerProperties properties;
9
10 protected ErrorPageCustomizer(ServerProperties properties) {
11 this.properties = properties;
12 }
13
14 public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
15 ErrorPage errorPage = new ErrorPage(this.properties.getServletPrefix() +
16 this.properties.getError().getPath());
17 errorPageRegistry.addErrorPages(new ErrorPage[]{errorPage});
18 }
19 }
20
21 //进入this.properties.getError().getPath()方法,获取如下信息,得到/error请求。
22 @Value("${error.path:/error}")
23 private String path = "/error";//系统出现错误以后来到error请求进行处理;(web.xml注册的错误页面规则)
【2】BasicErrorController 处理 /error错误请求:注意:text/html 和 */*就是在此处生效。
1 @Bean
2 @ConditionalOnMissingBean(
3 value = {ErrorController.class},
4 search = SearchStrategy.CURRENT
5 )
6 public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) {
7 return new BasicErrorController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers);
8 }
9
10 //进入BasicErrorController对象,获取如下信息
11 @Controller
12 @RequestMapping({"${server.error.path:${error.path:/error}}"})
13 public class BasicErrorController extends AbstractErrorController {
14 private final ErrorProperties errorProperties;
15
16 public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties) {
17 this(errorAttributes, errorProperties, Collections.emptyList());
18 }
19
20 @RequestMapping(
21 produces = {"text/html"}//产生html类型的数据;浏览器发送的请求来到这个方法处理
22 )
23 public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
24 HttpStatus status = this.getStatus(request);
25 Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
26 response.setStatus(status.value());
27
28 //去哪个页面作为错误页面;包含页面地址和页面内容
29 ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
30 return modelAndView != null?modelAndView:new ModelAndView("error", model);
31 }
32
33 @RequestMapping
34 @ResponseBody//产生json数据,其他客户端来到这个方法处理;
35 public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
36 Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
37 HttpStatus status = this.getStatus(request);
38 return new ResponseEntity(body, status);
39 }
40 }
☞ 如上代码中提到的错误页面解析代码,进入此方法: this.resolveErrorView(request, response, status, model);
1 protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status, Map<String, Object> model) {
2 Iterator var5 = this.errorViewResolvers.iterator();
3 ModelAndView modelAndView;
4 do {
5 //从所有的ErrorViewResolver得到ModelAndView
6 if(!var5.hasNext()) {
7 return null;
8 }
9
10 ErrorViewResolver resolver = (ErrorViewResolver)var5.next();
11 modelAndView = resolver.resolveErrorView(request, status, model);
12 } while(modelAndView == null);
13
14 return modelAndView;
15 }
【3】最终的响应页面是由 DefaultErrorViewResolver 解析得到的:最重要的信息是,SpringBoot 默认模板引擎的 /error目录下获取 ‘status’.xml 错误页面,也可以通过 4xx.xml来统配 404.xml和 400.xml等等,但是优先获取精准的页面。如果模板引擎中不存在,则会从静态页面中获取错误页面。否则返回系统默认错误页面。
1 @Bean
2 @ConditionalOnBean({DispatcherServlet.class})
3 @ConditionalOnMissingBean
4 public DefaultErrorViewResolver conventionErrorViewResolver() {
5 return new DefaultErrorViewResolver(this.applicationContext, this.resourceProperties);
6 }
7
8 //进入DefaultErrorViewResolver类中
9 public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
10 ModelAndView modelAndView = this.resolve(String.valueOf(status), model);
11 if(modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
12
13 //调用时viewname = status ***重要
14 modelAndView = this.resolve((String)SERIES_VIEWS.get(status.series()), model);
15 }
16
17 return modelAndView;
18 }
19
20 private ModelAndView resolve(String viewName, Map<String, Object> model) {
21
22 //默认SpringBoot可以去找到一个页面? error/404
23 String errorViewName = "error/" + viewName;
24
25 //模板引擎可以解析这个页面地址就用模板引擎解析
26 TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.
27 getProvider(errorViewName, this.applicationContext);
28
29 //模板引擎可用的情况下返回到errorViewName指定的视图地址,
30 //当模板引擎不可用,就在静态资源文件夹下找errorViewName对应的页面 error/404.html
31 return provider != null?new ModelAndView(errorViewName, model):this.resolveResource(errorViewName, model);
32 }
【4】DefaultErrorAttributes:在页面添加错误信息,供我们使用。
1 @Bean
2 @ConditionalOnMissingBean(
3 value = {ErrorAttributes.class},
4 search = SearchStrategy.CURRENT
5 )
6 public DefaultErrorAttributes errorAttributes() {
7 return new DefaultErrorAttributes();
8 }
9
10 //进入DefaultErrorAttributes类中,发现此方法给视图中添加了status状态等信息,供我们使用。
11 public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
12 Map<String, Object> errorAttributes = new LinkedHashMap();
13 errorAttributes.put("timestamp", new Date());
14 this.addStatus(errorAttributes, requestAttributes);
15 this.addErrorDetails(errorAttributes, requestAttributes, includeStackTrace);
16 this.addPath(errorAttributes, requestAttributes);
17 return errorAttributes;
18 }
三、定制错误 JSON数据
【1】自定义异常处理类,返回定制的 JSON数据。通过上述的分析,我们得知:①、可以完全编写一个 ErrorController的实现类,或者继承 AbstractErrorController的子类,放入容器中。②、也可以自定义异常处理类,返回 JSON数据。③、页面上的数据或 JSON返回的数据都是可以通过 errorAttributes.getErrorAttributes得到的。我们可以自定义属于自己的 ErrorAttributes。
1 //首先我们可以通过自定义异常处理,来确定返回的数据,但这个不够灵活,我们可以与③结合使用
2 /**
3 * @RequestMapping启动应用后,被 @ExceptionHandler、@InitBinder、@ModelAttribute 注解的方法,都会作用在 被 @RequestMapping
4 * 注解的方法上。
5 */
6 @ControllerAdvice
7 public class MyExceptionHandler {
8 @ResponseBody
9 @ExceptionHandler(UserNotExistException.class)
10 public Map<String,Object> handlerException(Exception e, HttpServletRequest request){
11 Map<String,Object> map = new HashMap<String,Object>();
12 request.setAttribute("javax.servlet.error.status_code","500");
13 map.put("code","user.notexist");
14 map.put("message",e.getMessage());
15 return map;
16 }
17 }
18
19 //③自定义ErrorAttributes,一定要加入容器
20 @Component
21 public class MyErrorAttributes extends DefaultErrorAttributes{
22 @Override
23 public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
24 //获取默认的配置,在此基础上添加自己的需求
25 Map<String, Object> map = super.getErrorAttributes(requestAttributes, includeStackTrace);
26 //自定义自己需要的属性
27 map.put("company","yintong");
28
29 //获取我们在异常处理类中添加的信息,
30 /*注意:当我们需要结合使用的时候异常处理必须return "forward:/error";将请求转发出去,不能直接返回map对象,
31 同时要去掉@responseBody注解,否则ErrorAttributes不生效*/
32 map.put("ext",requestAttributes.getAttribute("ext",requestAttributes.SCOPE_REQUEST));
33 return map;
34 }
35 }
【2】效果展示:


----关注公众号,获取更多内容----
SpringBoot——定制错误页面及原理的更多相关文章
- springboot 定制错误页面
项目中经常遇到的异常情况 400-Bad Request 401-Unauthorized If the request already included Authorization credenti ...
- SpringBoot定制错误页面
(1)有模板引擎的情况下,例如404错误,将会在thymeleaf的templates的error下寻找404.html,如果找不到再寻找4xx.html *所有4开头的错误状态码如果找不到特定的ht ...
- SpringBoot定制错误的Json数据
(1)自定义异常处理&返回定制Json数据 @ControllerAdvice public class MyExceptionHandler { @ResponseBody @Excepti ...
- SpringBoot自定义错误页面,SpringBoot 404、500错误提示页面
SpringBoot自定义错误页面,SpringBoot 404.500错误提示页面 SpringBoot 4xx.html.5xx.html错误提示页面 ====================== ...
- springboot自定义错误页面
springboot自定义错误页面 1.加入配置: @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { re ...
- 【Laravel5】 定制错误页面
laravel5 所有异常错误都由类 App\Exceptions\Handler 处理,该类包含两个方法: report 和 render . 这里我们只看 render ...
- Spring boot错误处理以及定制错误页面
如果是浏览器访问,返回错误页面 注意浏览器发送请求的请求头: 注意区别其他客户端哦比如 postman 如果是其他客户端,返回一个Json数据 原理可以参照ErrorMvcAutoConfigura ...
- springboot系列六、springboot配置错误页面及全局异常
一.spring1.x中处理方式 @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { return new ...
- Springboot - 自定义错误页面
Springboot 没找到页面或内部错误时,会访问默认错误页面.这节我们来自定义错误页面. 自定义错误页面 1.在resources 目录下面再建一个 resources 文件夹,里面建一个 err ...
- apache定制错误页面
编辑配置文件,错误页面定制支持三种形式: 1. 普通文本 2. 本地跳转 3. 外部跳转 [root@ken-node2 ~]# vim /etc/httpd/conf/httpd.conf ... ...
随机推荐
- SourceInsight4破解
2017/10/18 更新 1. 安装原版软件:Source Insight Version 4.0.0092 - March 20, 2018 2. 下载激活程序:sourceinsight_40 ...
- 目前为止最完善专业的微信小程序商城
购买商业版(368元): http://market.zhenzikj.com/detail/82.html帮助文档:https://www.kancloud.cn/crmeb/crmeb/66242 ...
- HTML——VSCODE配置笔记
# 使用VSCODE编辑前端代码 ### 1.问题一:无法根据!快速生成html标准代码 (1).首先看文件命名是否出错,即文件名后缀名.html (2).第一步没出错,就在新建文件的编辑状态下拨动C ...
- 【APT】APT-C-41下载器组件样本分析
前言 APT-C-41(又被称为蓝色魔眼.Promethium.StrongPity),该APT组织最早的攻击活动可以追溯到2012年.该组织主要针对意大利.土耳其.比利时.叙利亚.欧洲等地区和国家进 ...
- ubuntu中用vscode
下载vscode 终端中输入code运行 输入sudo apt-get update sudo apt-get install gcc 此报错解决方式: sudo rm /var/lib/dpkg/l ...
- Vue router前端路由配置以及实现tab切换
vue router 安装:npm install vue-router或cnpm install vue-router或yarn add vue-router. 安装完成之后会在package.js ...
- Python pexpect 库的简单使用
一.Python pexpect 库的使用 在终端中许多命令都有与用户交互的场景,例如切换用户时需要手动输入密码,安装应用有时要输入默认配置等.这对 shell 自动化脚本十分不便.expect 命令 ...
- Linux习题
1.判断/etc/inittab文件是否大于100行,如果大于,则显示"/etc/inittab is a big file."否者显示"/etc/inittab is ...
- ssm框架基本原理
一.前言 SM框架是标准的MVC模式,将整个系统划分为四层:View层,Controller层,Service层,Dao层 SSM(Spring+SpringMVC+MyBatis)框架集由Sprin ...
- js计算某一天是本月的第几周
需要实现一个小需求,计算2月24号是2月的第几周: 废话不多说,直接上代码: /** * a = d = 当前日期 * b = 6 - w = 当前周的还有几天过完(不算今天) * a + b 的和在 ...