Spring Boot中的全局异常处理

时间:2022-10-09 23:17:29 类型:JAVA
字号:    

  在项目开发过程中,不管是对底层数据库的操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异常需要处理。如果对每个过程都单独作异常处理,那系统的代码耦合度会变得很高,此外,开发工作量也会加大而且不好统一,这也增加了代码的维护成本。

  针对这种实际情况,我们需要将所有类型的异常处理从各处理过程解耦出来,这样既保证了相关处理过程的功能单一,也实现了异常信息的统一处理和维护。同时,我们也不希望直接把异常抛给用户,应该对异常进行处理,对错误信息进行封装,然后返回一个友好的信息给用户。

        方法如下:

  1. 定义返回的统一 json 结构

import lombok.Data;

@Data
public class EJson {
    /**
     * 异常码
     */
    protected String code;
    /**
     * 异常信息
     */
    protected String msg;
    public EJson() {
        this.code = "200";
        this.msg = "操作成功";
    }
    public EJson(String code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}

  2. 处理系统异常

  新建一个 GlobalExceptionHandler 全局异常处理类,

        @ControllerAdvice 注解即可拦截项目中抛出的异常

        @ResponseBody 注解是为了异常处理完之后给调用方输出一个 json 格式的封装 数据。

如下:

        第一个拦截异常:参数缺失的时候,会抛出 HttpMessageNotReadableException

        第二个拦截异常:空指针异常,   NullPointerException

       以此类推: 可以定义更多的异常.....................

        最后把再定义一个 Exception异常, 前边没有被拦截的异常,统统都会在这里被拦截

       Exception 异常是父类,所有异常都会继承该异常,所以我们可以直接拦截 Exception 异常,一劳永逸

@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
    // 打印log
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    /**
     * 缺少请求参数异常
     * @param ex HttpMessageNotReadableException
     * @return
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public EJson handleHttpMessageNotReadableException(
            MissingServletRequestParameterException ex) {
            logger.error("缺少请求参数,{}", ex.getMessage());
        return new EJson("400", "缺少必要的请求参数");
    }

    /**
     * 空指针异常
     * @param ex NullPointerException
     * @return
     */
    @ExceptionHandler(NullPointerException.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public EJson handleTypeMismatchException(NullPointerException ex) {
        logger.error("空指针异常,{}", ex.getMessage());
        return new EJson("500", "空指针异常了");
    }

    /**
     * 系统异常 预期以外异常
     * @param ex
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public EJson handleUnexpectedServer(Exception ex) {
        logger.error("系统异常:", ex);
        return new EJson("500", "系统发生异常,请联系管理员");
    }
}

定义控制器做个测试:

@RestController
    @RequestMapping("/exception")
public class ExceptionController {
        private static final Logger logger =
                LoggerFactory.getLogger(ExceptionController.class);
        @PostMapping("/test")
        public EJson test(@RequestParam("name") String name,
                          @RequestParam("sex") String sex) {
            logger.info("name:{}", name);
            logger.info("sex:{}", sex);
            return new EJson();
        }

        @RequestMapping("/null")
        public EJson test1(String name,String sex){
            if(sex.equals("男")){
                logger.info("性别:{}",sex);
            }
            return new EJson();
        }
        @RequestMapping("/byzero")
        public EJson test2(){
            int result = 1 / 0;
            return new EJson();
        }
    }

通过Postman访问做个测试

1.jpg2.jpg

3.jpg

<