-
错误机制处理
-
默认效果
- 浏览器返回一个错误页面,包含错误码,错误信息
- 其他客户端返回json数据,包含错误码,错误信息
-
ErrorMvcAutoConfiguration错误处理的自动配置类
- DefaultErrorAttributes:获取错误页面能展示的错误信息
@Override public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) { Map<String, Object> errorAttributes = new LinkedHashMap<>(); errorAttributes.put("timestamp", new Date()); addStatus(errorAttributes, webRequest); addErrorDetails(errorAttributes, webRequest, includeStackTrace); addPath(errorAttributes, webRequest); return errorAttributes; }
- BasicErrorController
//处理默认/error请求 @Controller @RequestMapping("${server.error.path:${error.path:/error}}") public class BasicErrorController extends AbstractErrorController { //返回html数据 @RequestMapping(produces = MediaType.TEXT_HTML_VALUE) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections .unmodifiableMap(getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView != null) ? modelAndView : new ModelAndView("error", model); } //返回json类型的数据 @RequestMapping public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { HttpStatus status = getStatus(request); if (status == HttpStatus.NO_CONTENT) { return new ResponseEntity<>(status); } Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); return new ResponseEntity<>(body, status); }
- ErrorPageCustomizer
//系统出现错误以后来到error请求进行处理,web.xml注册的错误页面规则 @Value("${error.path:/error}") private String path = "/error";
- DefaultErrorViewResolver
-
- 错误处理步骤:一旦系统出现4XX和5XX的错误时,ErrorPageCustomizer就会生效,就会来到/error请求处理,就会被BasicErrorController处理
,DefaultErrorViewResolver决定响应的页面是哪个,DefaultErrorAttributes获取能展示的错误信息
- 页面能展示的错误信息:
- timestamp:时间戳
- status:状态码
- error:错误提示
- exception:异常对象
- message:异常消息
- errors:JSR303数据校验的错误
3. 如何定制错误响应
- 定制错误响应页面:
- 如果使用了模板引擎
- 直接在resource目录下的template目录下新建error/状态码.html【将精确错误状态码.html放在模板引擎的error目录下】
- 以文件名4xx.html和5xx.html文件放在模板引擎的目录下,如果没有精确的状态码会直接使用4xx或者5xx的页面返回
- 没有模板引擎
- 可以直接放在静态资源文件夹下,可以直接获取出来
- 如果模板引擎和静态资源文件夹下都没有找到错误页面,就显示springboot的默认空白错误页面
```
@Override
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
throws Exception {
if (response.isCommitted()) {
String message = getMessage(model);
logger.error(message);
return;
}
response.setContentType(TEXT_HTML_UTF8.toString());
StringBuilder builder = new StringBuilder();
Date timestamp = (Date) model.get("timestamp");
Object message = model.get("message");
Object trace = model.get("trace");
if (response.getContentType() == null) {
response.setContentType(getContentType());
}
builder.append("<html><body><h1>Whitelabel Error Page</h1>").append(
"<p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>")
.append("<div id='created'>").append(timestamp).append("</div>")
.append("<div>There was an unexpected error (type=").append(htmlEscape(model.get("error")))
.append(", status=").append(htmlEscape(model.get("status"))).append(").</div>");
if (message != null) {
builder.append("<div>").append(htmlEscape(message)).append("</div>");
}
if (trace != null) {
builder.append("<div style='white-space:pre-wrap;'>").append(htmlEscape(trace)).append("</div>");
}
builder.append("</body></html>");
response.getWriter().append(builder.toString());
}
```
- 抛出一个自己的异常信息
1. 创建一个自己的异常信息类
```
public class UserNotExistException extends RuntimeException {
public UserNotExistException() {
super("用户不存在");
}
}
```
2. templates/error/5xx.html新建文件
```html
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>错误</title>
</head>
<body>
<h1 >[[${status}]]</h1>
<h1 >[[${timestamp}]]</h1>
<h1 >[[${exception}]]</h1>
<h1 >[[${message}]]</h1>
</body>
</html>
```
3. 写一个接口,抛出自己的异常
- **定制错误响应json信息**
- 写一个MyExceptionHandler
```
@ControllerAdvice
public class MyExceptionHandler {
// 指定返回的数据转为json
@ResponseBody
// 设置当系统抛出哪个异常的时候执行下面的处理
@ExceptionHandler(UserNotExistException.class)
public Map<String, Object> handleException(Exception e){
Map<String,Object> map = new HashMap<>();
map.put("code","423");
map.put("msg",e.getMessage());
return map;
}
}
```
- 此时抛出的UserNotException前端接收到的数据为
```json
{"msg":"用户不存在","code":"423"}
```
网友评论