SpringBoot2.x统一异常捕获@RestControllerAdvice

今天主要给大家介绍以下传统项目中如何解决代码中存在的大量try....catch...代码问题。在传统的项目框架中,我们不可避免的会遇到程序抛出异常的情况,有些异常不会影响程序的正常运行,而有些异常则是致命的,经常会导致我们的项目宕机。而为了尽可能的避免这种情况,我们一般会对代码进行异常捕获处理,这就造成代码中会存在大量的异常捕获代码try....catch...,这使得我们的代码易读性及美观性都相当的差。今天就给大家介绍以下如何捕获全局异常,从而避免对每一次请求进行异常捕获。

话不多说,上代码::

  1. 首先我们希望我们的接口每次返回的数据都是一定的格式的,这样前端访问接口就可以直观的了解接口的可用性。所以我们新建类ResultBean来作为统一返回接口的Bean
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ResultBean {

    private Integer code; //执行编号
    private String message; //返回信息
    private Object data; //封装内容

}
  1. 其次,我们不同的接口返回的异常也是不尽相同的,所以我们新建枚举类ResultEnum来定义我们的返回类型。
public enum ResultEnum {

    SUCCESS(200,"操作成功"),

    FAIL(500,"操作失败"),

    EXCEPTION(400,"系统错误"),

    NOPERMISS(401,"用户没有权限");

    private Integer code;
    private String message;

    private ResultEnum(Integer code,String message){
        this.code = code;
        this.message = message;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

  1. 当然我们需要自己的异常处理类MyException
public class MyException extends Exception {

    private Integer code;

    public MyException(String msg){
        super(msg);
    }

    public MyException(Integer code,String msg){
        super(msg);
        this.code = code;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }
}
  1. 接下来就是今天的重点了@RestControllerAdvice@ExceptionHandler进行异常捕获处理
@RestControllerAdvice
public class ExceptionAdvice {

    private static Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class);

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResultBean defaultException(Exception e){
        logger.error("系统发生异常:{},请及时处理!",e.getMessage());
        if(null != e.getMessage()){
            if(e.getMessage().contains("Subject does not have permission")){
                return ResultBean.builder()
                        .code(ResultEnum.NOPERMISS.getCode())
                        .message(ResultEnum.NOPERMISS.getMessage())
                        .build();
            }
            return ResultBean.builder()
                    .code(ResultEnum.EXCEPTION.getCode())
                    .message(ResultEnum.EXCEPTION.getMessage())
                    .build();
        }
        return ResultBean.builder()
                .code(ResultEnum.EXCEPTION.getCode())
                .message("空指针异常")
                .build();
    }

    @ExceptionHandler(value = MyException.class)
    @ResponseBody
    public ResultBean myException(MyException e){
        e.printStackTrace();
        Integer code = e.getCode();
        String message = e.getMessage();

        if(null == e.getCode()){
            code = ResultEnum.EXCEPTION.getCode();
        }

        if (null == e.getMessage()){
            message = ResultEnum.EXCEPTION.getMessage();
        }

        return ResultBean.builder()
                .code(code)
                .message(message)
                .build();
    }

}
  1. 为了以后的使用方便,我们可以编写自己的返回信息封装工具类ResultUtil
public class ResultUtil {

    /**
     * 返回错误信息
     * @param message 错误信息
     * @return
     */
    public static ResultBean error(String message){
        return ResultBean.builder()
                .code(ResultEnum.FAIL.getCode())
                .message(message)
                .build();
    }

    /**
     * 返回错误信息
     * @param code 错误编码
     * @param message 错误信息
     * @return
     */
    public static ResultBean error(Integer code,String message){
        return ResultBean.builder()
                .code(code)
                .message(message)
                .build();
    }

    /**
     * 返回错误信息
     * @param resultEnum 枚举类
     * @return
     */
    public static ResultBean error(ResultEnum resultEnum){
        return ResultBean.builder()
                .code(resultEnum.getCode())
                .message(resultEnum.getMessage())
                .build();
    }

    /**
     * 返回错误信息
     * @return
     */
    public static ResultBean error(){
        return ResultBean.builder()
                .code(ResultEnum.FAIL.getCode())
                .message(ResultEnum.FAIL.getMessage())
                .build();
    }

    /**
     * 返回操作成功信息
     * @param message 枚举类
     * @return
     */
    public static ResultBean success(String message){
        return ResultBean.builder()
                .code(ResultEnum.SUCCESS.getCode())
                .message(message)
                .build();
    }

    /**
     * 返回操作成功信息
     * @param code 成功编号
     * @param message 成功信息
     * @return
     */
    public static ResultBean success(Integer code,String message){
        return ResultBean.builder()
                .code(code)
                .message(message)
                .build();
    }

    /**
     * 返回操作成功信息
     * @param resultEnum 枚举类
     * @return
     */
    public static ResultBean success(ResultEnum resultEnum){
        return ResultBean.builder()
                .code(resultEnum.getCode())
                .message(resultEnum.getMessage())
                .build();
    }

    /**
     * 返回操作成功信息
     * @return
     */
    public static ResultBean success(){
        return ResultBean.builder()
                .code(ResultEnum.SUCCESS.getCode())
                .message(ResultEnum.SUCCESS.getMessage())
                .build();
    }

    /**
     * 返回操作成功信息
     * @return
     */
    public static ResultBean success(Object data){
        return ResultBean.builder()
                .code(ResultEnum.SUCCESS.getCode())
                .message(ResultEnum.SUCCESS.getMessage())
                .data(data)
                .build();
    }

    /**
     * 返回操系统异常信息
     * @param message 枚举类
     * @return
     */
    public static ResultBean exception(String message){
        return ResultBean.builder()
                .code(ResultEnum.EXCEPTION.getCode())
                .message(message)
                .build();
    }

    /**
     * 返回操系统异常信息
     * @param resultEnum 枚举类
     * @return
     */
    public static ResultBean exception(ResultEnum resultEnum){
        return ResultBean.builder()
                .code(resultEnum.getCode())
                .message(resultEnum.getMessage())
                .build();
    }

    /**
     * 返回操系统异常信息
     * @return
     */
    public static ResultBean exception(){
        return ResultBean.builder()
                .code(ResultEnum.EXCEPTION.getCode())
                .message(ResultEnum.EXCEPTION.getMessage())
                .build();
    }

}

至此,我们的全局异常捕获及统一接口返回就实现完成了

大家可以编写测试Controoller进行测试

@PostMapping("/login")
    @ResponseBody
    public Object login(String username, String password){
        if(StringUtils.isEmpty(username)){
            return ResultUtil.error("用户名为空");
        }

        if(StringUtils.isEmpty(password)){
            return ResultUtil.error("密码为空");
        }
        
        /**
        * 登录业务流程
		*/
        return  ResultUtil.success("登录成功");
    }

你可能感兴趣的:(SpringBoot,java,exception,spring,boot)