【springboot异常处理】用异常信息枚举类处理异常,使用自定义异常封装异常对象,返回统一异常处理结果

1.目录:
在这里插入图片描述

异常信息枚举类

由于在业务中,有很多异常,针对不同的业务,可能给出的提示信息不同,所以为了方便项目异常信息管理,我们一般会定义一个异常信息枚举类。

public enum BusinessMsgEnum {
    /** 参数异常*/
    PARMETER_EXCEPTION("102", "参数异常!"),
    /** 等待超时*/
    SERVICE_TIME_OUT("103", "服务调用超时!"),
    /** 参数过大*/
    PARMETER_BIG_EXCEPTION("102", "输入的图片数量不能超过50 张!"),
    /** 500 : 一劳永逸的提示也可以在这定义*/
    UNEXPECTED_EXCEPTION("500", "系统发生异常,请联系管理员!");
// 还可以定义更多的业务异常
    /**
     * 消息码
     */
    private String code;
    /**
     * 消息内容
     */
    private String msg;
    private BusinessMsgEnum(String code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public String getCode() {
        return code;
    }

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

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
    // set get 方法
}

自定义异常类


public class BusinessErrorException extends RuntimeException{
    private static final long serialVersionUID = -7480022450501760611L;
    /**
     * 异常码
     */
    private String code;
    /**
     * 异常提示信息
     */
    private String message;
    public BusinessErrorException(BusinessMsgEnum businessMsgEnum) {
        this.code = businessMsgEnum.getCode();
        this.message = businessMsgEnum.getMsg();
    }
//    在构造方法中,传入我们上面自定义的异常枚举类,所以在项目中,如果有新的异常信
//    息需要添加,我们直接在枚举类中添加即可,很方便,做到统一维护,然后再拦截该异
//    常时获取即可。
    public String getCode() {
        return code;
    }

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

    @Override
    public String getMessage() {
        return message;
    }

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

自定义响应数据

@Data
@JsonInclude(value = JsonInclude.Include.NON_NULL)//这样配置了以后为null的数据就不会再返回给前端了。比如data为null时前端不会收到data这一数据

public class JSONResult {
    
    /**
     *
  
     * @Description: 自定义响应数据结构
     *                 这个类是提供给门户,ios,安卓,微信商城用的
     *                 门户接受此类数据后需要使用本类的方法转换成对于的数据类型格式(类,或者list)
     *                 其他自行处理
     *                 200:表示成功
     *                 500:表示错误,错误信息在msg字段中
     *                 501:bean验证错误,不管多少个错误都以map形式返回
     *                 502:拦截器拦截到用户token出错
     *                 555:异常抛出信息
     * Copyright: Copyright (c) 2016
     * Company:Nathan.Lee.Salvatore

     */


        // 定义jackson对象
        private final ObjectMapper MAPPER = new ObjectMapper();

        // 响应业务状态
        private Integer status;

        // 响应消息
        private String msg;

        // 响应中的数据
        private Object data;

        private String ok;    // 不使用

        public JSONResult build(Integer status, String msg, Object data) {
            return new JSONResult(status, msg, data);
        }

        public  JSONResult ok(Object data) {
            return new JSONResult(data);
        }

        public JSONResult ok() {
            return new JSONResult(null);
        }

        public  JSONResult errorMsg(String msg) {
            return new JSONResult(500, msg, null);
        }

        public JSONResult errorMap(Object data) {
            return new JSONResult(501, "error", data);
        }

        public JSONResult errorTokenMsg(String msg) {
            return new JSONResult(502, msg, null);
        }

        public JSONResult errorException(String msg) {
            return new JSONResult(555, msg, null);
        }

        public JSONResult() {

        }

//    public static LeeJSONResult build(Integer status, String msg) {
//        return new LeeJSONResult(status, msg, null);
//    }

        public JSONResult(Integer status, String msg, Object data) {
            this.status = status;
            this.msg = msg;
            this.data = data;
        }
        public JSONResult(Integer status, String msg) {
            this.status = status;
            this.msg = msg;

        }
        public JSONResult(Object data) {
            this.status = 200;
            this.msg = "OK";
            this.data = data;
        }

        public Boolean isOK() {
            return this.status == 200;
        }

        public Integer getStatus() {
            return status;
        }

        public void setStatus(Integer status) {
            this.status = status;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public Object getData() {
            return data;
        }

        public void setData(Object data) {
            this.data = data;
        }

        /**
         *
         * @Description: 将json结果集转化为LeeJSONResult对象
         *                 需要转换的对象是一个类
         * @param jsonData
         * @param clazz
         * @return
         *
  
         */
        public JSONResult formatToPojo(String jsonData, Class<?> clazz) {
            try {
                if (clazz == null) {
                    return MAPPER.readValue(jsonData, JSONResult.class);
                }
                JsonNode jsonNode = MAPPER.readTree(jsonData);
                JsonNode data = jsonNode.get("data");
                Object obj = null;
                if (clazz != null) {
                    if (data.isObject()) {
                        obj = MAPPER.readValue(data.traverse(), clazz);
                    } else if (data.isTextual()) {
                        obj = MAPPER.readValue(data.asText(), clazz);
                    }
                }
                return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);
            } catch (Exception e) {
                return null;
            }
        }

        /**
         *
         * @Description: 没有object对象的转化
         * @param json
         * @return
         *

         */
        public JSONResult format(String json) {
            try {
                return MAPPER.readValue(json, JSONResult.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        /**
         *
         * @Description: Object是集合转化
         *                 需要转换的对象是一个list
         * @param jsonData
         * @param clazz
         * @return
         *

         */
        public JSONResult formatToList(String jsonData, Class<?> clazz) {
            try {
                JsonNode jsonNode = MAPPER.readTree(jsonData);
                JsonNode data = jsonNode.get("data");
                Object obj = null;
                if (data.isArray() && data.size() > 0) {
                    obj = MAPPER.readValue(data.traverse(),
                            MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
                }
                return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);
            } catch (Exception e) {
                return null;
            }
        }

        public String getOk() {
            return ok;
        }

        public void setOk(String ok) {
            this.ok = ok;
        }

    }

全局异常处理类

全局异常处理类,使用@ControllerAdvice来表示它为全局异常
@ControllerAdvice 注解包含了@Component 注解,说明在Spring Boot 启动时,也会把该类作为组件交给Spring 来管理。除此之外,该注解还有个basePackages 属性,该属性是用来拦截哪个包中的异常信息,一般我们不指定这个属性,我们拦截项目工程中的所有异常
@ResponseBody 注解是为了异常处理完之后给调用方输出一个json 格式的封装数据。
在项目中如何使用呢?Spring Boot 中很简单,在方法上通过@ExceptionHandler 注解来指定具体的异常,然后在方法中处理该异常信息,最后将结过统一的json 结构体返回给调用者。


@ControllerAdvice
@ResponseBody
//全局异常处理类,使用@ControllerAdvice来表示它为全局异常
//@ControllerAdvice 注解包含了@Component 注解,说明在Spring Boot 启动时,也会把该类作为组件交给Spring 来管理。除此之外,该注解还有个basePackages 属性,该属性是用来拦截哪个包中的异常信息,一般我们不指定这个属性,我们拦截项目工程中的所有异常

public class GlobalExceptionHandler {
    // 打印log
    private static final Logger logger =
            LoggerFactory.getLogger(ExceptionHandler.class);

    /**
     * 缺少请求参数异常
     * @param ex HttpMessageNotReadableException
     * @return
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public JSONResult handleHttpMessageNotReadableException(
            MissingServletRequestParameterException ex) {
        logger.error("缺少请求参数,{}", ex.getMessage());
        return new JSONResult(400, "缺少必要的请求参数");
    }

    @ExceptionHandler(NullPointerException.class)//空指针异常
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public JSONResult handleTypeMismatchException(NullPointerException
                                                          ex) {
        logger.error("空指针异常,{}", ex.getMessage());
        return new JSONResult(500, "空指针异常了");
    }
/*
自定义异常
 */
    @ExceptionHandler(BusinessErrorException.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public JSONResult handleBusinessError(BusinessErrorException ex) {
        String code = ex.getCode();
        String message = ex.getMessage();
        return new JSONResult(Integer.parseInt(code), message);
    }
    }

测试

定义一个controller测试类用于测试刚才定义的异常。

@RestController
public class ExceptionController {
    private static final Logger logger =
            LoggerFactory.getLogger(ExceptionController.class);

   // 在业务代码中,我们可以直接模拟一下抛出业务异常,测试一下
   @GetMapping("/business")
   public JSONResult testException() {

           try {
               int i = 1 / 0;
           } catch (Exception e) {
               throw new
                       BusinessErrorException(BusinessMsgEnum.UNEXPECTED_EXCEPTION);
           }
           return new JSONResult();
       }
   }

在这里插入图片描述

总结

此文主要讲解了Spring Boot 的全局异常处理,包括异常信息的封装、异常信息的捕获和处理,以及在实际项目中,我们用到的自定义异常枚举类和业务异常的捕获与处理,在项目中运用的非常广泛,基本上每个项目中都需要做全局异常处理。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您想了解关于使用 @ExceptionHandler + @ControllerAdvice +枚举实现全局异常统一处理的内容,这是一个常用的方案,可以实现全局异常的捕获和处理,让程序更加健壮和稳定。 @ExceptionHandler注解用于标记一个方法,该方法用于处理指定的异常类型。@ControllerAdvice注解用于标记一个类,该类用于处理全局异常枚举则可以用于定义异常类型,方便异常处理时的统一管理。 在实现全局异常处理时,我们可以通过 @ExceptionHandler 注解来捕获指定的异常类型,并在方法中进行相应的处理。@ControllerAdvice注解可以让我们在一个类中定义多个 @ExceptionHandler方法,用于处理不同类型的异常。同时,我们也可以使用枚举来定义不同的异常类型,方便管理和调用。 下面是一个简单的示例,演示如何使用 @ExceptionHandler + @ControllerAdvice +枚举实现全局异常统一处理: ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(value = BusinessException.class) @ResponseBody public ResultVO handleBusinessException(BusinessException e) { return ResultVO.error(e.getCode(), e.getMessage()); } } public enum ExceptionEnum { PARAMETER_ERROR(1001, "参数错误"), DATA_NOT_FOUND(1002, "数据不存在"), SYSTEM_ERROR(5000, "系统错误"); private final int code; private final String message; ExceptionEnum(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public String getMessage() { return message; } } public class BusinessException extends RuntimeException { private final int code; public BusinessException(int code, String message) { super(message); this.code = code; } public BusinessException(ExceptionEnum exceptionEnum) { super(exceptionEnum.getMessage()); this.code = exceptionEnum.getCode(); } public int getCode() { return code; } } ``` 在上面的示例中,GlobalExceptionHandler类标记了@ControllerAdvice注解,用于全局异常处理。其中,handleBusinessException方法用于处理BusinessException异常返回一个ResultVO对象,其中包含错误码和错误信息。 BusinessException则是一个自定义的异常类,它包含一个code属性和一个message属性,用于表示异常的错误码和错误信息。同时,它还提供了一个构造方法,可以根据ExceptionEnum来构造一个BusinessException对象。 ExceptionEnum则是一个枚举类,包含了不同的异常类型,每个异常类型都有一个对应的错误码和错误信息。 在实际开发中,我们可以根据实际需求来定义不同的异常类型和错误码,以便更好地管理和调用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值