一:先看看springboot默认的错误处理机制
springboot默认会判断是否是浏览器(http请求头Accept是否含有 text/html)来选择返回html错误页面或json错误信息
原因在于BasicErrorController 控制器中的这两个映射
errorHtml响应来自浏览器的请求,而error响应来自其他客户端的请求;
在errorHtml中最后两句,如果没有自定义的页面,就会使用系统默认的错误解析视图
二:那么如何定制自己的错误页面呢?
由BasicErrorController 控制器中errorHtml的最后调用
1 ModelAndView modelAndView = resolveErrorView(request, response, status, model);
获取用户自定义的对应的错误页面
(DefaultErrorViewResolver)
resolve方法或先查找模板引擎的页面中是否有error/(错误状态码) 页面,如果有就直接返回视图,如果没有就查找静态资源文件下有没有,如果也没有就返回null,使用springboot默认的
这样的话,我们就只需要在模板引擎解析目录或者静态资源目录的error文件夹下放入(错误状态码).html 即可,(也可以是4xx , 5xx)
模板页面里能获取到一些信息
timestamp:时间戳
status:状态码
error:错误提示
exception:异常对象
message:异常消息
errors:JSR303数据校验的错误都在这里
例如:(我是thymleaf)
1 <!DOCTYPE html>
2 <html lang="en" xmlns:th="http://www.thymeleaf.org">
3 <head>
4 <meta charset="UTF-8">
5 <!--/*@thymesVar id="status" type="java"*/-->
6 <title th:text="${status}"></title>
7 </head>
8 <body>
9 <h2>timestamp : [[${timestamp}]]</h2>
10 <h2>status : [[${status}]]</h2>
11 <h2>error : [[${error}]]</h2>
12 <h2>exception : [[${exception}]]</h2>
13 <h2>message : [[${message}]]</h2>
14 <h2>errors : [[${errors}]]</h2>
15 </body>
16 </html>
三:定制json格式错误响应
利用自定义异常处理机制来定制json数据响应
1 @ControllerAdvice
2 public class MyExceptionHandler {
3 @ResponseBody
4 @ExceptionHandler(Exception.class)
5 public Map<String, Object> exceptionHandler1(Exception e){
6 Map<String, Object> map = new HashMap<>();
7 map.put("status", 400);
8 map.put("msg", e.getMessage());
9 map.put("data", null);
10 return map;
11 }
12 }
1 @GetMapping("/222")
2 public void test4(){
3 throw new RuntimeException("23333");
4 }
四:需要像springboot默认的一样自动选择响应html页面还是json
html错误页面上的数据和json的数据都是通过errorAttributes.getErrorAttributes得到的,
所以我们可以在自定义异常处理中转发到/error, 并自定义ErrorAttributes,来实现
1 @ControllerAdvice
2 public class MyExceptionHandler {
3 @ExceptionHandler(Exception.class)
4 public String exceptionHandler1(Exception e, HttpServletRequest request){
5 Map<String, Object> map = new HashMap<>();
6 map.put("msg", e.getMessage());
7 map.put("data", null);
8 request.setAttribute("errorMap", map);
9
10 request.setAttribute("javax.servlet.error.status_code",400);
11
12 return "forward:/error";
13 }
14 }
1 @Component
2 public class MyErrorAttributes extends DefaultErrorAttributes {
3 @Override
4 public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
5 Map<String, Object> map = (Map<String, Object>) requestAttributes.getAttribute("errorMap", 0);
6
7 return map;
8 }
9 }
还有之前的4xx.html
效果:
五:完全由我们自己实现
编写一个ErrorController的实现类【或者是编写AbstractErrorController的子类】,放在容器中,来达到自定义效果