开发者学堂课程【SpringBoot快速掌握 - 核心技术:错误处理原理 & amp ;定制错误页面】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/612/detail/9256
错误处理原理 & amp ;定制错误页面
一、SpringBoot 默认处理机制
默认效果:1.浏览器返回一个默认的错误页面
Whitelabel Error Page
This application has no explicit mapping for /error,so you are seeing this as a fallback
Mon Feb 26 17:33:50 GMT+08:00 2018
There was an unexpected error (typeNot Found,status=404) No message availabl
2.如果是其他客户端,默认响应一个 json 数据
原理:可以参照 Error
M
vAutoConfiguration
;错误处理的自动配置。
给容器中添加一下组件
D
efaultErrorAttrlbutes;
在页面共享信息
public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
Map<String, Object> errorAttributes = new LinkedHashMap();
errorAttributes.put("timestamp", new Date());
errorAttributes.put("path", request.path());
Throwable error = this.getError(request);
HttpStatus errorStatus = this.determineHttpStatus(error);
errorAttributes.put("status", errorStatus.value());
errorAttributes.put("error", errorStatus.getReasonPhrase());
errorAttributes.put("message", this.determineMessage(error));
this.handleException(errorAttributes, this.determineException(error), includeStackTrace);
return errorAttributes;
}
B
asicErrorController;
@
Controller
@
RequestMapping(“$
{
server.error.path;$
{
error.path;/error
}}
”)
public
class BasicErrorController extends AbstractErrorController{
@
RequestMapping(prodeces = “text/html”)//
产生
html
类型的数据;浏览器发送的请求来到这个方式处理
p
ublic ModelAndView errorHtml(HttpServletRequest request,HttpServletResponse response){
H
ttpStatus status = getStatus(request);
M
ap<String,Object> model = Collections.unmodifiableMap(getErrorAttributes(request,isIncludeStackTrace(request,MediaType.TEXT_HTML)));
r
esponse.setStatus(status.value());
M
odelAndView modelAndView = resolveErrorView(request,response,status,model);
return(modelAndView == null? new ModelAndView(“error”,model) ;modelAndView);
}
@
RequstMapping
@
ResponseBody //
产生
json
数据;其他客户端来到这个方法处理;
p
ublic ResponseEntity<Map<String,Object>> error(HttpServleRequest request){
Map<String,Object> body = getErrorAttributes(request,isIncludeStackTrace(request,MediaType.ALL));
HttpStatus status = getStatus(request);
r
eturn new ResponseEntity<Map<String,Object>>(body,status);
}
E
rroPageCusomizer:
public class ErrorProperties {
@Value("${error.path:/error}")
private String path = "/error";
public String getPath() {
return this.path;
}
...
}
D
efaultErrorViewResolver
;
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
ModelAndView modelAndView = this.resolve(String.valueOf(status.value()), model);
if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
modelAndView = this.resolve((String)SERIES_VIEWS.get(status.series()), model);
}
return modelAndView;
}
private ModelAndView resolve(String viewName, Map<String, Object> model) {
//默认
springboot
会找到某个页面 error/404
String errorViewName = "error/" + viewName;
//模板引擎可以解析页面地址就使用模板引擎解析
TemplateAvailabilityProvider provider =
this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext);
//模板引擎不可用,就在静态资源文件夹下找
errorViewName
对应的页面
return provider != null ? new ModelAndView(errorViewName, model) :
this.resolveResource(errorViewName, model);
}
步骤:
一但系统出现4xx或者5xx之类的错误; ErrorPageCustomizer 就会生效(定制错误的响应规则);就会来到 /error 请求;就会被 BasicErrorController 处理;
如果定制错误响应:
如何定制错误的页面;
有模板引擎的情况下; error/ 状态码【将错误页面命名为错误状态码 .html 放在模板引起文件夹里面的 error 文件夹下】,发生此状态码错误的就会来到对应的页面;
可以使用 4xx 和5xx作为错误页面的文件名来匹配这种类型的所有错误,精确优先(优先寻找精确的状态码 .html );
页面能够获取的信息;
timestamp:时间戳
status:状态码
error:错误提示
exception:异常对象
message:异常消息
errors:JSR303数据校验的错误都在这里
没有模块引擎(模块引擎找不到这个错误页面),静态资源文件夹下找;
以上都没有错误页面,就是默认来到 SpringBoot 默认的错误提示页面
响应页面;去哪个页面是由 DefaultErrorViewResolver 解析得到的
protected ModelAndView resolveErrorView(HttpServletRequest request,
HttpServletResponse response, HttpStatus status, Map<String, Object> model) {
//所有的
ErrorViewResolver
得到
ModelAndView
Iterator var5 = this.errorViewResolvers.iterator();
ModelAndView modelAndView;
do {
if (!var5.hasNext()) {
return null;
}
ErrorViewResolver resolver = (ErrorViewResolver)var5.next();
modelAndView = resolver.resolveErrorView(request, status, model);
} while(modelAndView == null);
return modelAndView;
}
如何定制错误的 json 数据;