• Springboot 自定义异常处理


    Springboot 自定义异常处理需要使用到 @ControllerAdvice 和 @ExceptionHandler 这两个注解

    @ControllerAdvice 注解是 Spring 3.2 提供的一个新注解,它是一个 Controller 增强器,可以对 Controller 中被 @RequestMapping 注解的方法加上一些我们自定义的逻辑处理,最常用的就是用作异常处理

    @ExceptionHandler 注解的作用是用来指明异常的类型,即如果这里指定为 NullpointerException ,则数组越界异常就不会进到这个方法中来.该注解需要配合 @ControllerAdvice 注解一起使用,可以对异常进行统一的处理,规定返回的是 Json 格式或者是跳转到一个错误的页面

     

    话不多说,Springboot 要实现自定义异常,这里会有下面几种方式,这里只讲两种,如果想要更多的方式,可以参考官方文档

    1、全面接管 Springboot 异常处理,覆盖默认的异常处理机制

    Springboot 的异常处理控制器是 BasicErrorController,如果容器中已经存在了一个 ErrorController 的实现类,那么该控制器就不会注入到容器中

    @Bean
    // 如果容器中没有 ErrorController 的实现类,那么判断条件才成立,才会将 basicErrorController 注入到容器中
    @ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)
    public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) {
    	return new BasicErrorController(errorAttributes, this.serverProperties.getError(),
    			this.errorViewResolvers);
    }
    

    从 springboot 的默认配置中就可以看到,如果我们自定义一个 ErrorController 实现类,那么 Springboot 默认的配置就会失效,我们可以完全的自定义 springboot 的异常处理

    @ControllerAdvice(annotations = Controller.class)
    public class MyExceptionAdvice implements ErrorController {
        @ResponseBody
        // 这里可以传入 Exception.class,也可以传入自定义的 MyException.class
        @ExceptionHandler(Exception.class)
        // 这里的参数有很多,根据自己的需求选择合适的参数,具体可以参考官方文档
        public Map<String, Object> myErrorHandler(Exception e, HttpServletRequest request) {
            // 返回 Json 格式
            Map<String, Object> map = new HashMap<>();
            if (e instanceof MyException) {
                MyException me = (MyException) e;
                map.put("errorCode", me.getCode());
                map.put("errorMessage", me.getMessage());
            }else if(e instanceof IndexOutOfBoundsException){
                map.put("errorMessage",e.getMessage());
            }
            return map;
        }
        
        @Override
        public String getErrorPath() {
            return "hello errors";
        }
    }
    

    这里也可以写两个方法,使用@ExceptionHandler(MyException)、@ExceptionHandler(IndexOutOfBoundsException) 来拦截对应的异常,并进行相关的逻辑处理.当然也可以如上面这种方式使用同一个方法进行统一处理.

    自定义异常实现 RuntimeException 

    public class MyException extends RuntimeException {
        private String code;
        private String message;
        
        public MyException(String code, String message) {
            this.code = code;
            this.message = message;
        }
    
        // 省略 get / set 方法
    }
    

    控制器

    @Controller
    public class SpringbootErrorController {
        @RequestMapping("/error01")
        public String error01() {
            throw new MyException("404", "resource not found exception!!!");
        }
    
        @RequestMapping("/error02")
        public String error02() {
            throw new IndexOutOfBoundsException("数组下标越界异常...");
        }
    }
    

    浏览器分别发送 localhost:8080/error01、localhost:8080/error02 ,结果如下

    {"errorMessage":"resource not found exception!!!","errorCode":"404"}
    {"errorMessage":"数组下标越界异常..."}
    

    如果不需要返回json数据,而要渲染某个页面模板返回给浏览器,那么可以这么实现

    @ControllerAdvice(annotations = Controller.class)
    public class MyExceptionAdvice implements ErrorController {
        @ResponseBody
        @ExceptionHandler(Exception.class)
        public ModelAndView myErrorHandler(Exception e, HttpServletRequest request) {
            // 渲染到页面
            ModelAndView mav = new ModelAndView();
    
            if (e instanceof MyException) {
                MyException me = (MyException) e;
                mav.addObject("errorCode", me.getCode());
                mav.addObject("errorMessage", me.getMessage());
            }else if(e instanceof IndexOutOfBoundsException){
                mav.addObject("errorMessage", e.getMessage());
            }
            mav.setViewName("error/4xx");
            return mav;
        }
    
        @Override
        public String getErrorPath() {
            return "hello errors";
        }
    }
    

      

    2、使用 Springboot 默认的控制器 BasicErrorController,该控制器中错误的数据信息来源是 DefaultErrorAttributes ,我们只需要编写一个类 MyDefaultErrorAttributes 继承 DefaultErrorAttributes ,这样容器中就只会存在MyDefaultErrorAttributes 这个 bean 

    @Bean
    // 如果容器中已经存在了 ErrorAttributes 的实现类,那么 DefaultErrorAttributes 就不会再注入 IOC 容器了
    @ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)
    public DefaultErrorAttributes errorAttributes() {
    	return new DefaultErrorAttributes();
    }
    

    具体实现如下:

    // 自定义类注入容器中,这样 DefaultErrorAttributes 就不会再注入容器中了
    @Component
    public class MyDefaultErrorAttributes extends DefaultErrorAttributes {
        @Override
        public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
            Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);
            errorAttributes.put("name","xiaomaomao");
            errorAttributes.put("age","22");
            return errorAttributes;
        }
    }
    

      

     

  • 相关阅读:
    python_day11 mysql
    python_day10 多线程 协程 IO模型
    python_day09 多进程 多线程 协程 paramiko模块
    python_day08 接口与归一化设计 多态与多态性 封装 面向对象高级 异常处理 网络编程
    python_day07 常用模块xml/configparser/hashlib/subprocess 面向对象程序设计
    python_day06 匿名函数与内置函数 常用模块
    python_day05 协程函数 面向过程编程 递归和二分法 模块和包的使用 常用模块 开发代码规范
    python_day04 函数嵌套 名称空间和作用域 闭包 装饰器 迭代器 生成器 列表解析 三元表达式 生成器表达式
    python_day03 文件处理复习和函数定义调用参数对象
    python_day02 基本数据类型操作,字符编码,文件处理
  • 原文地址:https://www.cnblogs.com/xiaomaomao/p/14026931.html
Copyright © 2020-2023  润新知