栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot(10) -- Web开发-- 异常处理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot(10) -- Web开发-- 异常处理

SpringBoot2学习笔记

源码地址

四、Web开发 4.9)异常处理

4.9.1)异常处理默认规则

默认情况下,Spring Boot提供/error处理所有错误的映射;

对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,响应一个“ whitelabel”错误视图,以HTML格式呈现相同的数据,访问不存在路径内容页面如下:

 

要对其进行自定义,error/下的4xx,5xx页面会被自动解析,添加view页面4xx.html,代码如下:




  
  
  
  
  
​
  404 Page
​
  
  
​
  
  

​

​
    ​        
                       

page not found            

We Couldn’t Find This Page             Back To Home        

​    
​ ​

页面如下:

 

4.9.2)定制错误处理逻辑

  1. 自定义错误页: error/404.html error/5xx.html;有精确的错误状态码页面就匹配精确,没有就找 4xx.html;如果都没有就触发白页;

  2. @ControllerAdvice+@ExceptionHandler处理全局异常;底层是 ExceptionHandlerExceptionResolver 支持的,新建GlobalExceptionHandler.java ,代码如下:

    @Slf4j
    @ControllerAdvice
    public class GlobalExceptionHandler {
        //处理数学运算异常和空指针异常
        @ExceptionHandler({ArithmeticException.class, NullPointerException.class})
        public String handleArithException(Exception e) {
            log.error("异常是:{}", e);
            //当遇到数学运算异常和空指针异常时跳转到login页面[视图地址]
            return "login";
        }
    }

  3. @ResponseStatus+自定义异常 ;底层是 ResponseStatusExceptionResolver :把responsestatus注解的信息底层调用 response.sendError(statusCode, resolvedReason);tomcat发送到/error访问错误页, 新建UserTooManyExceptionr.java ,代码如下:

    // 当 http状态码为 HttpStatus.FORBIDDEN时,进入该异常进行处理
    @ResponseStatus(value = HttpStatus.FORBIDDEN, reason = "用户数量太多")
    @Slf4j
    public class UserTooManyException extends RuntimeException {
    ​
        public UserTooManyException() {
            log.error("异常是:{用户数量太多}");
        }
    ​
        public UserTooManyException(String message) {
            super(message);
        }
    }

    修改接口内容进行测试:

     @GetMapping("/dynamic_table")
        public String dynamic_table(Model model) {
            //表格内容的遍历
            List users = Arrays.asList(new User("zhangsan", "123456"),
                    new User("lisi", "123444"),
                    new User("haha", "aaaaa"),
                    new User("hehe ", "aaddd"));
    ​
            // @ResponseStatus+自定义异常
            if (users.size() > 3) {
                throw new UserTooManyException();
            }
    ​
            model.addAttribute("users", users);
    ​
            return "table/dynamic_table";
        }

    测试:浏览器访问:http://localhost:8080/dynamic_table,页面如下:

  4.  

  5. Spring底层的异常:如参数类型转换异常;DefaultHandlerExceptionResolver 处理框架底层的异常

    response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());

 

  1. 自定义实现 HandlerExceptionResolver 处理异常;可以作为默认的全局异常处理规则,新建CustomerHandlerExceptionResolver.java ,代码如下:

    //优先级,数字越小优先级越高,设为最高优先级
    @Order(value = Ordered.HIGHEST_PRECEDENCE)
    @Component
    public class CustomerHandlerExceptionResolver implements HandlerExceptionResolver {
        @Override
        public ModelAndView resolveException(HttpServletRequest request,
                                             HttpServletResponse response,
                                             Object handler, Exception ex) {
    ​
            try {
                response.sendError(511, "我喜欢的错误");
            } catch (IOException e) {
                e.printStackTrace();
            }
            return new ModelAndView();
        }
    }

  2. ErrorViewResolver 实现自定义处理异常; ○ response.sendError 。error请求就会转给controller

    ○ 你的异常没有任何人能处理。tomcat底层 response.sendError。error请求就会转给controller

    ○ basicErrorController 要去的页面地址是 ErrorViewResolver ;

4.9.3)异常处理自动配置原理

ErrorMvcAutoConfiguration:自动配置异常处理规则

  1. 容器中的组件:类型:DefaultErrorAttributes -> id:errorAttributes

    ■ public class DefaultErrorAttributes implements ErrorAttributes, HandlerExceptionResolver

    ■ DefaultErrorAttributes:定义错误页面中可以包含哪些数据

  2.  


 

  1. 容器中的组件:类型:BasicErrorController --> id:basicErrorController(json+白页 适配响应)

■ 处理默认 /error 路径的请求;页面响应 new ModelAndView("error", model); ■ 容器中有组件 View->id是error;(响应默认错误页) ■ 容器中放组件 BeanNameViewResolver(视图解析器);按照返回的视图名作为组件的id去容器中找View对象。

  1. 容器中的组件:类型:DefaultErrorViewResolver -> id:conventionErrorViewResolver

■ 如果发生错误,会以HTTP的状态码 作为视图页地址(viewName),找到真正的页面 ■ error/404、5xx.html

4.9.4)异常处理步骤流程

  1. 执行目标方法,目标方法运行期间有任何异常都会被catch、而且标志当前请求结束;并且用 dispatchException 进行封装,源码如下图:

 

  1. 进入视图解析流程(页面渲染)

源码如下图:

 

processDispatchResult方法源码如下:

    private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {
        boolean errorView = false;
        if (exception != null) {
            if (exception instanceof ModelAndViewDefiningException) {
                this.logger.debug("ModelAndViewDefiningException encountered", exception);
                mv = ((ModelAndViewDefiningException)exception).getModelAndView();
            } else {
                Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;
                mv = this.processHandlerException(request, response, handler, exception);
                errorView = mv != null;
            }
        }
​
        if (mv != null && !mv.wasCleared()) {
            this.render(mv, request, response);
            if (errorView) {
                WebUtils.clearErrorRequestAttributes(request);
            }
        } else if (this.logger.isTraceEnabled()) {
            this.logger.trace("No view rendering, null ModelAndView returned.");
        }
​
        if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
            }
​
        }
    }
  1. 处理handler发生的异常

mv = processHandlerException:处理handler发生的异常,处理完成返回ModelAndView;

  • 遍历所有的 handlerExceptionResolvers,看谁能处理当前异常【HandlerExceptionResolver处理器异常解析器】,如下图:

 

HandlerExceptionResolver源码如下:

public interface HandlerExceptionResolver {
    @Nullable
    ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);
}

  • 系统默认的异常解析器,如下图:

DefaultErrorAttributes先来处理异常。把异常信息保存到rrequest域,并且返回null;

默认没有任何人能处理异常,所以异常会被抛出:

  1. 如果没有任何人能处理最终底层就会发送 /error 请求。会被底层的BasicErrorController处理

  2. 解析错误视图;遍历所有的 ErrorViewResolver【错误页面解析器】看谁能解析

  3. 默认的 DefaultErrorViewResolver ,作用是把响应状态码作为错误页的地址,error/500.html

  4. 模板引擎最终响应这个页面 error/500.html

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/971055.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号