SpringBoot--自定义错误页面、数据

简单配置

第一种情况:不使用模板

如果不需要向用户展示详细的错误信息,那么可以把错误信息定义成静态页面,直接在resources/static目录下创建error目录,然后在error目录中创建错误展示页面。

错误展示页面的规则有两种:

  1. 4xx.html、5xx.html
  2. 直接使用相应码命名文件,例如404.html、500.html

第二种情况:使用模板

如果要使用HTML模板,以Thymeleaf为例,Thymeleaf页面模板默认处于**classpath:/templates/**下,因此在该目录下创建error目录,再创建错误页面即可,规则和上面的一致。

示例:使用HTML模板
在这里插入图片描述
错误页面:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
</head>
<body>
    404<br/>
    <p th:text="${timestamp}"></p>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
</head>
<body>
500<br/>
<p th:text="${timestamp}"></p>
</body>
</html>

提供一个会抛异常的Controller

@Controller
public class HelloController {

    @RequestMapping("/hello")
    public String hello(){
        int i = 1 / 0;
        return "hello";
    }
}

测试404:
在这里插入图片描述

测试500:
在这里插入图片描述

注意:

  • 如果定义了多个错误页面,则响应码.html页面的优先级高于4xx.html、5xx.html页面的优先级;
  • 动态页面的优先级高于静态页面的优先级;

复杂配置

1. 自定义Error数据

SpringBoot返回的Error信息一共有5条,分别是timestamp、status、error、message以及path。在BasicErrorController的errorHtml方法和error方法中,都是通过getErrorAttributes方法获取Error信息的。该方法最终会调用到DefaultErrorAttributes类的getErrorAttributes方法,而DefaultErrorAttributes类是在ErrorMvcAutoConfiguration中默认提供的。

ErrorMvcAutoConfiguration类的errorAttributes方法源码如下:

	@Bean
    @ConditionalOnMissingBean(
        value = {ErrorAttributes.class},
        search = SearchStrategy.CURRENT
    )
    public DefaultErrorAttributes errorAttributes() {
        return new DefaultErrorAttributes(
			this.serverProperties.getError().isIncludeException());
    }

可以看出,当系统没有提供ErrorAttributes时,才会采用DefaultErrorAttributes。
所以,我们只需要提供一个自己的ErrorAttributes即可,而DefaultErrorAttributes是ErrorAttributes的子类,因此只需要继承DefaultErrorAttributes,重写getErrorAttributes方法即可。

实例:

@Component
public class MyErrorAttibute extends DefaultErrorAttributes {
    @Override
    public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
        Map<String, Object> map = super.getErrorAttributes(requestAttributes, includeStackTrace);
        map.put("msg","粗错啦!");//增加自定义信息
        map.remove("error");//删除error信息
        return map;
    }
}

测试500:
在这里插入图片描述
测试404:
在这里插入图片描述注意: 返回的JSON的数据也会随之改变。

自定义Error视图

BasicErrorControllererrorHtml方法中调用resolveErrorView方法获取一个ModelAndView实例。resolveErrorView方法是由ErrorViewResolver提供的。

		@Bean
        @ConditionalOnBean({DispatcherServlet.class})
        @ConditionalOnMissingBean
        public DefaultErrorViewResolver conventionErrorViewResolver() {
            return new DefaultErrorViewResolver(this.applicationContext, this.resourceProperties);
        }

从源码中可以看出,如果我们没有定义ErrorViewResolver,那么默认使用的ErrorViewResolver是DefaultErrorViewResolver,所以如果想自定义Error视图,只需要提供自己的ErrorViewResolver即可。

@Component
public class MyErrorViewResolver implements ErrorViewResolver {
    @Override
    public ModelAndView resolveErrorView(HttpServletRequest httpServletRequest, HttpStatus httpStatus, Map<String, Object> map) {
        ModelAndView modelAndView = new ModelAndView("/error/errorPage");
        modelAndView.addObject("xxx","resolverErrorView中添加的数据");
        modelAndView.addAllObjects(map);//系统定义的数据
        return modelAndView;
    }
}
  • 自定义MyErrorViewResolver实现ErrorViewResolverResolver接口并实现接口中的resolverErrorView方法,使用@Component注解将该类注册到Spring容器中。
  • 在resolveErrorView方法中,最后一个Map参数就是SpringBoot提供的默认的5条Error信息(可以按照前面自定义的步骤对这5条消息进行修改)。在resolveErrorView方法中,返回一个ModelAndView,在ModelAndView中设置Error视图和Error数据。
  • 理论上,开发者也可以通过实现ErrorResolver接口来实现Error数据的自定义,但如果只是单纯的想自定义Error数据,建议京城DefaultErrorAttributes。

页面:errorPage

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
</head>
<body>
<h1>自定义错误视图</h1>
<p th:text="${timestamp}"></p><br/>
<p th:text="${status}"></p><br/>
<p th:text="${error}"></p><br/>
<p th:text="${message}"></p><br/>
<p th:text="${path}"></p><br/>
<p th:text="${msg}"></p><br/>
<p th:text="${xxx}"></p><br/>
</body>
</html>

测试:
在这里插入图片描述
在这里插入图片描述

注意: 此时无论请求发生4xx的错误还是发生5xx的错误,都会跳转到errorPage.html页面。

完全自定义

前面的两种方式都是对BasicErrorController类中的某个环节进行修补。查看Error自动化配置类ErrorMvcConfiguration,可以发现BasicErrorController本身只是一个默认的配置:

	@Bean
    @ConditionalOnMissingBean(
        value = {ErrorController.class},
        search = SearchStrategy.CURRENT
    )
    public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) {
        return new BasicErrorController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers);
    }

可以看出,若开发者没有提供自己的ErrorController,则SpringBoot提供BasicErrorController作为默认的ErrorController。因为,如果想完全自定义错误处理,只需要提供一个子集的ErrorController即可。

提供自己的ErrorController有两种方式:

  • 实现ErrorController接口
  • 继承BasicErrorController

因为BasicErrorController已经实现了很多功能,所以选择继承BasicErrorController。

@Controller
public class MyErrorController extends BasicErrorController {

    @Autowired
    public MyErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties, List<ErrorViewResolver> errorViewResolvers) {
        super(errorAttributes, serverProperties.getError(), errorViewResolvers);
    }

    @Override
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = getStatus(request);
        Map<String, Object> map = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
        map.put("myError", "myError");
        ModelAndView modelAndView = new ModelAndView("/error/myErrorPage", map, status);
        return modelAndView;
    }

    @Override
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> map = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
        map.put("myError", "myError");
        HttpStatus status = getStatus(request);
        return new ResponseEntity<>(map, status);
    }
}
  • 自定义MyErrorController继承BasicErrorController并添加@Controller注解,注册到容器中。
  • 由于BasicErrorController没有无参构造方法,因此在创建BasicErrorController实例的时候需要传递参数,在MyErrorController的构造方法上添加@Autowired注解注入参数。
  • 重写errorHtml和error方法。

页面:myErrorPage

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
</head>
<body>
<h1>完全自定义</h1>
<p th:text="${timestamp}"></p><br/>
<p th:text="${status}"></p><br/>
<p th:text="${error}"></p><br/>
<p th:text="${message}"></p><br/>
<p th:text="${path}"></p><br/>
<p th:text="${msg}"></p><br/>
<p th:text="${xxx}"></p><br/>
<p th:text="${myError}"></p>
</body>
</html>

测试:
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值