美文网首页程序员
SpringBoot错误处理

SpringBoot错误处理

作者: 小杨小杨神采飞杨 | 来源:发表于2020-05-03 12:53 被阅读0次

    springboot默认的错误处理机制:
    浏览器:返回一个错误页面:


    错误页面

    其他客户端:返回一个Json数据


    Json数据

    原理:可以参考ErrorMvcAutoConfiguration类
    DefaultErrorAttributes:错误页面显示的信息
    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:定制错误响应规则

    getPath
    path
    /error
    系统出现错误以后,默认响应规则为跳转到/error请求进行处理

    DefaultErrorViewResolver:去哪个响应页面

        @Override
        public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
            //所有的ErrorViewResolver得到ModelAndView 
            ModelAndView modelAndView = resolve(String.valueOf(status.value()), model);
            if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
                modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);
            }
            return modelAndView;
        }
    

    步骤:
    一但系统出现4xx或5xx的错误,ErrorPageCustomizer就会生效,来到/error请求,被BasicErrorController处理,去哪个响应页面由DefaultErrorViewResolver处理,错误信息由DefaultErrorAttributes解析

    目的:定制错误响应
    1)、如何定制错误页面?
    有模板引擎的情况下,将错误页面以状态码命名,放在模板引擎文件夹下的error文件夹下,发生此状态码错误就会来到这个页面,也可以使用4xx或5xx来命名,当没有精确的错误状态码匹配时,就会根据错误类型访问对应的4xx或5xx页面,原则是精确优先,有精确的先访问精确的状态码.html

    命名
    404
    4xx

    错误页面可以获取的信息:
    timestamp:时间戳
    status:状态码
    error:错误提示
    exception:异常信息
    message:错误信息
    errors:JSR303数据校验错误信息

    在自定义错误页面获取错误信息:


    获取错误信息
    获取成功

    没有模板引擎默认在静态资源文件夹下寻找错误页面,命名规则一致
    但是没有模板引擎则无法获取错误信息

    2)、如何定制错误Json数据?
    默认Json格式数据


    默认

    创建自定义异常


    自定义异常
    获取了自定义的错误
    修改显示的数据
    @ControllerAdvice//指明这是一个异常处理器
    public class myExceptionHandler {
        @ResponseBody//返回Json数据
        @ExceptionHandler(userNotFoundException.class)//标注处理什么异常
        public Map<String,Object> handler(Exception e){
            Map<String,Object> map = new HashMap<>();
            map.put("code","user.notFound");//处理异常返回的信息
            map.put("message",e.getMessage());
            return map;//返回map生成的Json数据
        }
    }
    
    测试结果
    问题:此时不论浏览器还是其他客户端,访问该异常都是Json格式
    浏览器访问
    解决:设置自适应
    @ExceptionHandler(userNotFoundException.class)
        public String handler(Exception e){
            Map<String,Object> map = new HashMap<>();
            map.put("code","user.notFound");
            map.put("message",e.getMessage());
            return "forward:/error";//转发到/error请求达到自适应效果
        }
    
    测试结果

    问题:不是我们自定义的页面了,且状态码为200,这是分明是正确访问的结果
    解决:在自定义异常处理器时,设置异常的状态码


    设置异常的状态码
    测试结果

    问题:自定义的信息无法显示


    自定义的信息无法显示
    解决:自定义错误属性
    自定义错误属性
    创建自定义错误属性类,继承DefaultErrorAttributes
    @Component
    public class myErrorAttributs extends DefaultErrorAttributes {
        @Override
        public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
            //使用getErrorAttributes获取的map集合就是转换为错误Json信息的map集合
            Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace);
            //往map集合内添加新的键值对,就能添加Json的信息
            map.put("myInfo","cn.yzx");
            //或者传入同名key就可以覆盖已有的信息
            map.put("status",499);
            //也可以从各种域中获取共享的信息,0表示request域
            Map<String, Object> ext = (Map<String, Object>) webRequest.getAttribute("ext", 0);
            //添加到map中即可
            map.put("ext",ext);
            return map;
        }
    }
    
    测试结果

    相关文章

      网友评论

        本文标题:SpringBoot错误处理

        本文链接:https://www.haomeiwen.com/subject/tbxdghtx.html