SpringBoot-错误处理机制
原理
可以参照ErrorMvcAutoConfiguration,错误处理的自动配置
给容器中添加了以下组件
DefaultErrorAttributes:
帮我们在页面共享信息
BasicErrorController:
处理默认的/error请求,返回html数据或json数据
ErrorPageCustomizer:
系统出现错误后,来到error请求进行处理
DefaultErrorViewResolver:
默认SpringBoot可以去找到一个页面(error/xxx),模板引擎能解析页面地址就用模板引擎解析,模板引擎可用就返回到erorViewName指定的视图地址,不可用则就在静态资源文件夹下找errorViewName对应的页面
步骤:一旦系统出现4xx或5xx之类的错误,ErrorPageCustomizer就会生效(定制错误的响应规则);就会来到/error请求;就会被BasicErrorController处理:
响应页面:去哪个页面是由DefaultErrorViewResolver解析得到的
如何定制错误响应
如何定制错误的页面
- 有模板引擎的情况下:error/状态码
- 将错误页面命名为错误状态码.html放在resources/templates文件夹里面的error文件夹下,发生此状态码的错误就会来到对应的页面
- 可以使用4xx和5xx作为错误页面的文件名来匹配这种类型的所有错误,精确名(如404.html)优先
- 页面能获取的信息:
- timestamp:时间戳
- status:状态码
- error:错误提示
- exception:异常对象
- message:异常消息
- errors:JSR303数据校验的错误
- 没有模板引擎(模板引擎下没有这个错误页面),静态资源文件夹下找
- 以上都没有错误页面,则默认到SpringBoot默认的错误提示页面
如何定制错误的json响应数据
自定义异常处理并返回定制json数据
无法自适应,浏览器和客户端返回的都是json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23// 1. 浏览器客户端返回的都是json
// @ExceptionHandler(UserNotExistExecption.class)
// @ResponseBody
// public Map<String,Object> handleExecption(Exception e){
// Map<String, Object> map = new HashMap<>();
// map.put("code", "user.notexist");
// map.put("message",e.getMessage());
// return map;
// }
public String handleExecption(Exception e, HttpServletRequest request){
Map<String, Object> map = new HashMap<>();
// 传入我们自己的错误状态码
request.setAttribute("javax.servlet.error.status_code",500);
map.put("code", "exception");
map.put("message",e.getMessage());
request.setAttribute("ext",map);
// 转发到/error进行自适应处理
return "forward:/error";
}转发到/error进行自适应处理
设置错误状态码
将定制数据携带出去
完全编写一个ErrorController的实现在(或编写AbstractErrorController的子类),放在容器中
页面上能用的数据或json返回能用的数据都是通过errorAttributes.getErrorAttributes得到
容器中DefaultErrorAttributes.getErrorAttributes();默认进行数据处理的,可自定义ErrorAttributes
1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyErrorAttributes extends DefaultErrorAttributes {
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace);
map.put("company","company");
// 从request域中获取数据,0->request域
Map<String ,Object> ext = (Map<String, Object>) webRequest.getAttribute("ext", 0);
map.put("ext",ext)
return map;
}
}