美文网首页
springboot之错误处理

springboot之错误处理

作者: eliteTyc | 来源:发表于2019-12-13 16:36 被阅读0次
    1. 错误机制处理
      1. 默认效果

        • 浏览器返回一个错误页面,包含错误码,错误信息
        • 其他客户端返回json数据,包含错误码,错误信息
      2. 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"}
            ```
    

    相关文章

      网友评论

          本文标题:springboot之错误处理

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