zoukankan      html  css  js  c++  java
  • Spring boot统一错误处理

    Spring boot统一错误处理

    期望定义一种规范,能让前端非常方便地处理接口错误。那么问题来了,前端怎么处理接口比较方便呢?

    前端脚手架通常会为所有的API请求写一个拦截器,其中拦截器很重要的一个能力就是对数据进行预处理。假设所有的正确数据都走向ajaxsuccess句柄,所有异常的数据都走向error句柄,成功或者失败的结果不会互相穿插,我们在定义句柄时无疑可以省却很多if-else分支。

    这是其一,其二:所有成功的数据都是ResultEnry格式,所有的错误都是errorcode+errormsg散列。我们在前端拦截器error句柄可以凭借errorcode联动错误信息配置非常方便的进行报错弹窗,省去大量接口类异常的逻辑代码。

    所以此处统一错误处理应满足两点:

    1. 后台接口不应该捕获并处理数据异常
    2. 抛给前端的异常统一格式

    自定义返回实体

    略。参考另一篇《Spring boot自定义返回实体》

    统一异常处理的两种方法

    1. 使用注解ControllerAdvice
    2. 实现ErrorController

    本例选择ControllerAdvice+自定义异常实现统一规范。下面简单介绍两种方式。

    ControllerAdvice

    该注解定义一个异常类,类里面定义多种异常句柄。

    @ControllerAdvice
    public class WebExceptionHandler {
        @ExceptionHandler
        public Result<Object> unknownException(Exception e) {
            return ResultEntry.error(ResultEnum.UNKNOWN_ERROR);
        }
        @ExceptionHandler
        public Result<Object> ioException(IOException e) {
            return ResultEntry.error(ResultEnum.UNKNOWN_ERROR);
        }
    }
    

    此方法只能监听到控制器抛出的异常

    ErrorController

    此方式会让框架默认的BaseErrorController无效

    @RestController
    public class WebExceptionHandler implements ErrorController {
        public Result<Object> error(HttpServletRequest request, HttpServletResponse response) {
            return ResultEntry.error(ResultEnum.UNKNOWN_ERROR);
        }
    }
    

    自定义运行时异常

    业务代码捕捉到异常,然后通过自定义异常层层往上抛,结合状态码枚举ResultEnum可以达到统一格式精准提示。

    自定义异常ServiceException

    public class ServiceException extends RuntimeException{
        private ResultEnum error;
    
        public ServiceException(ResultEnum error) {
            this.error = error;
        }
    
        public ResultEnum getError() {
            return error;
        }
    
        public void setError(ResultEnum error) {
            this.error = error;
        }
    }
    

    ControllerAdvice异常句柄

    @ControllerAdvice
    public class ServiceExceptionHander {
        @ExceptionHandler(ServiceException.class)
        @ResponseBody
        public <T> ResponseEntity<Result<T>> handle(ServiceException e){
            ResponseEntity<Result<T>> result = ResultEntry.error(e.getError());
            return result;
        }
    }
    

    ResultEntry组装返回的数据结构,利用ResponseEntity传递给前端错误码和错误实体。所以如果接口能拿到正确的数据,返回HttpStatus.OK,否则返回HttpStatus.BAD_GATEWAY;前端也会相应的触发ajaxsuccess或者error句柄。

    public class ResultEntry<T> implements Serializable{
    
        public static <T> ResponseEntity<Result<T>> success(T o) {
            return ResultEntry.response(ResultEnum.SUCCESS, o);
        }
        
        public static <T> ResponseEntity<Result<T>> success() {
            return ResultEntry.response(ResultEnum.SUCCESS);
        }
    
        public static <T> ResponseEntity<Result<T>> response(ResultEnum enu, T o) {
            Result<T> result = new Result<T>();
            result.setMsg(enu.getMsg());
            result.setStatus(enu.getStatus());
            result.setBody(o);
            return new ResponseEntity<Result<T>>(result, HttpStatus.OK);
        }
    
        public static <T> ResponseEntity<Result<T>> response(ResultEnum enu) {
            Result<T> result = new Result<T>();
            result.setMsg(enu.getMsg());
            result.setStatus(enu.getStatus());
            return new ResponseEntity<Result<T>>(HttpStatus.OK);
        }
    
        public static <T> ResponseEntity<Result<T>> error(ResultEnum enu) {
            Result<T> result = new Result<T>();
            result.setMsg(enu.getMsg());
            result.setStatus(enu.getStatus());
            return new ResponseEntity<Result<T>>(result, HttpStatus.BAD_GATEWAY);
        }
    }
    

    测试

    //controller
    @RestController()
    public class UpgradeController {
        @Autowired
        private UpgradeService upgradeService;
    
        @RequestMapping(value = "upgrade/records", method = RequestMethod.GET)
        public ResponseEntity<Result<ResultPage<UpgradeRecordDTO>>> getUpgradeRecords() {
            ResultPage<UpgradeRecordDTO> data = upgradeService.getUpgradeRecords();
            return ResultEntry.success(data);
        }
    }
    
    //service
    @Service
    public class UpgradeService {
        @Autowired
        private UpgradeRecordRepository recordRepository;
        // 查升级记录
        public ResultPage<UpgradeRecordDTO> getUpgradeRecords() throws ServiceException {
            Pageable pageable = PageRequest.of(0, 10);
            return new ResultPage<>(recordRepository.findAll(pageable));
        }
    }
    
  • 相关阅读:
    两台linux服务器相互拷贝文件的两个方法
    两台Linux服务器之间复制文件
    Linux两台服务器之间文件/文件夹拷贝
    Linux压缩和解压缩命令
    MongoDB学习笔记 1.1
    centos 7 MysSQL 5.6.39 二进制安装
    CentOS 7 Cobbler 配置 YUM仓库
    CentOS 7 Cobbler 自动化安装系统
    CentOS 7 Cobbler 安装
    OpenStack
  • 原文地址:https://www.cnblogs.com/longhx/p/15741036.html
Copyright © 2011-2022 走看看