Java自定义异常(优雅的处理异常)

Java自定义异常(优雅的处理异常)(本文较长,精华部分直接下拉)在复杂业务环境下,java自带的异常可能满足不了我们业务的需求,这个时候我们可以自定义异常来进行对业务异常的处理;首先,我们先对异常进行基本的解释:Throwable是所有Java程序中错误处理的父类,有两种子类:Error和Exception。Throwable是所有异常的根,java.lang.ThrowableError是错误,ja…

大家好,又见面了,我是你们的朋友全栈君。

(本文较长,精华部分直接下拉)

在复杂业务环境下,java自带的异常可能满足不了我们业务的需求, 这个时候我们可以自定义异常来进行对业务异常的处理;

首先,我们先对异常进行基本的解释:

Throwable是所有Java程序中错误处理的父类 ,有两种子类:Error和Exception。

 

Throwable是所有异常的根,java.lang.Throwable 
Error是错误,java.lang.Error 
Exception是异常,java.lang.Exception

Error:表示由JVM所侦测到的无法预期的错误,由于这是属于JVM层次的严重错误 ,导致JVM无法继续执行,因此,这是不可捕捉到的,无法采取任何恢复的操作,顶多只能显示错误信息。 Error类体系描述了Java运行系统中的内部错误以及资源耗尽的情形.应用程序不应该抛出这种类型的对象(一般是由虚拟机抛出).假如出现这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。

Exception:表示可恢复的例外,这是可捕捉到的.分为运行时异常,检查性异常.

Java提供了两类主要的异常 :runtime exception和checked exception。

**checked异常:I**O异常,以及SQL异常都是这种异常。 对于这种异常, JAVA编译器强制要求我们必需对出现的这些异常进行catch 。所以,面对这种异常不管我们是否愿意,只能自己去写一大堆catch块去处理可能的异常。 这类异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。 

runtime exception 运行时异常:我们可以不处理。当出现这样的异常时,总是由虚拟机接管。

出现运行时异常后,系统会把异常一直往上层抛,一直遇到处理代码。

如果没有处理块,到最上层,如果是多线程就由Thread.run()抛出,如果是单线程就被main()抛出。

抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,那么这整个程序也就退出了。

运行时异常是Exception的子类,也有一般异常的特点,是可以被Catch块处理的。只不过往往我们不对他处理罢了。

也就是说,你如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。

如果不想终止,则必须扑捉所有的运行时异常,决不让这个处理线程退出。

队列里面出现异常数据了,正常的处理应该是把异常数据舍弃,然后记录日志。

不应该由于异常数据而影响下面对正常数据的处理。在这个场景这样处理可能是一个比较好的应用,但并不代表在所有的场景你都应该如此。

如果在其它场景,遇到了一些错误,如果退出程序比较好,这时你就可以不太理会运行时异常,或者是通过对异常的处理显式的控制程序退出。

废话不多说,上干货

自定义,运行时异常;

先定义错误码枚举;规范错误集合

/**
 * 错误码接口
 */
package com.dyhospital.cloudhis.common.web.exception.reg.exception;

/**
 * 错误码接口
 * @author jacques
 * @version $Id: ErrorCode.java, v 0.1 2016年7月28日 下午3:50:01 zhouzhou
 */
public interface ErrorCode {

    /**
     * 获取错误码
     * @return
     */
    String getCode();

    /**
     * 获取错误信息
     * @return
     */
    String getDescription();
}
package com.dyhospital.cloudhis.common.web.exception.reg.exception;

/**
 * Description:
 * User: zhouzhou
 * Date: 2019-01-08
 * Time: 14:50
 */

import org.apache.commons.lang.StringUtils;

/**
 * 业务错误码
 * @author zhouzhou
 * @version $Id: BusinessErrorCodeEnum.java, v 0.1 2016年4月28日 下午5:44:00 zhouzhou Exp $
 */
public enum BizErrorCodeEnum implements ErrorCode {

    /** 未指明的异常 */
    UNSPECIFIED("500", "网络异常,请稍后再试"),
    NO_SERVICE("404", "网络异常, 服务器熔断"),

    // 通用异常
    REQUEST_ERROR("400", "入参异常,请检查入参后再次调用"),
    PAGE_NUM_IS_NULL("4001","页码不能为空"),
    PAGE_SIZE_IS_NULL("4002","页数不能为空"),
    ID_IS_NULL("4003","ID不能为空"),
    SEARCH_IS_NULL("4004","搜索条件不能为空"),


    // 短信相关
    SEND_MASSAGE_FAIL("30001","发送短消息失败"),
    SEND_MASSAGE_OFTEN("30002","操作发送短消息太频繁,请稍后再试"),
    MESSAGE_TEMPLATE_UNDEFINED("30003","短信模板未定义"),

    //支付相关
    CREATE_PAY_ORDER_FAIL("40001","创建订单支付失败"),
    UPDATE_PAY_ORDER_FAIL("40002","更新支付订单失败"),
    DEL_PAY_ORDER_FAIL("40003","更新支付订单失败"),
    PAY_ORDER_NO_EXISTS("40004","支付订单不存在"),
    REFUND_APPLY_NO_EXISTS("40005","退款申请不存在"),
    VERIFY_NOT_PASS("40006","验签"),
    RES_FAIL("40007","响应失败"),
    PAY_CHANNEL_IS_NULL("40008","支付渠道不能为空"),
    PAY_CHANNEL_PARAM_ERROR("40009","支付订单渠道参数错误"),



    ;

    /** 错误码 */
    private final String code;

    /** 描述 */
    private final String description;

    /**
     * @param code 错误码
     * @param description 描述
     */
    private BizErrorCodeEnum(final String code, final String description) {
        this.code = code;
        this.description = description;
    }

    /**
     * 根据编码查询枚举。
     *
     * @param code 编码。
     * @return 枚举。
     */
    public static BizErrorCodeEnum getByCode(String code) {
        for (BizErrorCodeEnum value : BizErrorCodeEnum.values()) {
            if (StringUtils.equals(code, value.getCode())) {
                return value;
            }
        }
        return UNSPECIFIED;
    }

    /**
     * 枚举是否包含此code
     * @param code 枚举code
     * @return 结果
     */
    public static Boolean contains(String code){
        for (BizErrorCodeEnum value : BizErrorCodeEnum.values()) {
            if (StringUtils.equals(code, value.getCode())) {
                return true;
            }
        }
        return  false;
    }
    
    @Override
    public String getCode() {
        return code;
    }

    @Override
    public String getDescription() {
        return description;
    }
}

 

再定义自定义异常类

package com.dyhospital.cloudhis.common.web.exception.reg.exception;

import lombok.Data;

/**
 * Description:业务异常类信息
 * User: zhouzhou
 * Date: 2019-05-08
 * Time: 13:35
 */
@Data
public class BizException extends RuntimeException {

    private static final long serialVersionUID = -7864604160297181941L;

    /** 错误码 */
    protected final ErrorCode errorCode;

    /**
     * 这个是和谐一些不必要的地方,冗余的字段
     * 尽量不要用
     */
    private String code;

    /**
     * 无参默认构造UNSPECIFIED
     */
    public BizException() {
        super(BizErrorCodeEnum.UNSPECIFIED.getDescription());
        this.errorCode = BizErrorCodeEnum.UNSPECIFIED;
    }

    /**
     * 指定错误码构造通用异常
     * @param errorCode 错误码
     */
    public BizException(final ErrorCode errorCode) {
        super(errorCode.getDescription());
        this.errorCode = errorCode;
    }

    /**
     * 指定详细描述构造通用异常
     * @param detailedMessage 详细描述
     */
    public BizException(final String detailedMessage) {
        super(detailedMessage);
        this.errorCode = BizErrorCodeEnum.UNSPECIFIED;
    }

    /**
     * 指定导火索构造通用异常
     * @param t 导火索
     */
    public BizException(final Throwable t) {
        super(t);
        this.errorCode = BizErrorCodeEnum.UNSPECIFIED;
    }

    /**
     * 构造通用异常
     * @param errorCode 错误码
     * @param detailedMessage 详细描述
     */
    public BizException(final ErrorCode errorCode, final String detailedMessage) {
        super(detailedMessage);
        this.errorCode = errorCode;
    }

    /**
     * 构造通用异常
     * @param errorCode 错误码
     * @param t 导火索
     */
    public BizException(final ErrorCode errorCode, final Throwable t) {
        super(errorCode.getDescription(), t);
        this.errorCode = errorCode;
    }

    /**
     * 构造通用异常
     * @param detailedMessage 详细描述
     * @param t 导火索
     */
    public BizException(final String detailedMessage, final Throwable t) {
        super(detailedMessage, t);
        this.errorCode = BizErrorCodeEnum.UNSPECIFIED;
    }

    /**
     * 构造通用异常
     * @param errorCode 错误码
     * @param detailedMessage 详细描述
     * @param t 导火索
     */
    public BizException(final ErrorCode errorCode, final String detailedMessage,
                        final Throwable t) {
        super(detailedMessage, t);
        this.errorCode = errorCode;
    }

    /**
     * Getter method for property <tt>errorCode</tt>.
     *
     * @return property value of errorCode
     */
    public ErrorCode getErrorCode() {
        return errorCode;
    }


}

 

接下来是使用类, 直接抛出异常枚举, 或者自定义其message

        if (billInfo != null) {
            throw new BizException(BizErrorCodeEnum.SEARCH_IS_NULL);
        }

 

        if (billInfo != null) {
            throw new BizException("错误啦");
        }

 

另外, 全局抓取异常向前端返回固定json格式的全局异常配置如下:



@ControllerAdvice
public class ControllerAdviceProcessor {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    protected MessageSource messageSource;

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public GenericResponse<?> handleException(HttpServletRequest request, Exception ex) {

        String code = "500";
        if (ex instanceof HttpMessageNotReadableException) {
            code = "400";
        } else if (ex instanceof HttpRequestMethodNotSupportedException) {
            code = "999";
        }
        String msg = null;


        if (ex instanceof BizException) {
            BizException bizException = (BizException) ex;
            msg = bizException.getMessage();
            code = bizException.getErrorCode().getCode();

        } else if (ex instanceof AccessDeniedException) {
            msg = "无权限访问";
            code = "403";
        } 
        if (msg == null) {
            msg = ex.getMessage();
        }
        GenericResponse<?> resp = new GenericResponse<>();
        resp.setCode(code);
        resp.setMessage(msg);
        logger.error("code: " + code + "  msg: " + msg, ex);
        return resp;
    }
}

 

 

 

 

 

 

 

 

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/144422.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • SaveFileDialog无法打开

    SaveFileDialog无法打开在线程中SaveFileDialog无法打开。Threadt=newThread(saveDialog);t.IsBackground=true;t.SetApartmentState(ApartmentState.STA);//加上这句就可以了t.Start();当前画面是报表画面,没用线程。主画面点击按钮,打开该画面,是在子线程中打开的,所以SaveFileDialog也无法直接打开…

    2022年10月8日
    2
  • 浅谈PO模式

    浅谈PO模式浅谈PO模式概述设计原则功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML图表FLowchart流程图导出与导入导出导入概述PO模式是自动化测试的一种常见设计思路,核心思想是通过对界面元素的封装减少冗余代码,同时在后期维护中,若元素定位发生变化,只需要调整页面元素封装的代码

    2022年5月13日
    62
  • Linux下的5款主流高可用集群软件介绍[通俗易懂]

    Linux下的5款主流高可用集群软件介绍[通俗易懂]Linux集群主要分成三大类:高可用集群(HighAvailabilityCluster)、负载均衡集群(LoadBalanceCluster)、科学计算集群(HighPerformanceComputingCluster)。其中高可用集群具有保障应用程序持续提供服务的能力,可以将因软、硬件、人为造成的故障对业务的影响降低到最小程度。在高可用集群中,最常见的就是两个节点做成的HA集群,有很多通俗的名称,比如“双机热备”、“双机互备”、“双机”。而在Linux平台下常见的高可用集群软件有

    2022年10月16日
    4
  • python进阶(13)装饰器[通俗易懂]

    python进阶(13)装饰器[通俗易懂]装饰器装饰器放在一个函数开始定义的地方,它就像一顶帽子一样戴在这个函数的头上。和这个函数绑定在一起。在我们调用这个函数的时候,第一件事并不是执行这个函数,而是将这个函数做为参数传入它头顶上这顶帽子,

    2022年7月28日
    9
  • 斜投影矩阵的性质_锥体体积怎么推导

    斜投影矩阵的性质_锥体体积怎么推导参考网址:https://gameinstitute.qq.com/community/detail/106203翻译http://www.terathon.com/lengyel/Lengyel-Oblique.pdf原文http://www.lsngo.net/2018/01/07/graphics_mirrorcamera_2/参考书籍:Mathematics.for.3D…

    2022年9月28日
    1
  • 抗渗等级p6是什么意思_混凝土p6是什么意思「建议收藏」

    抗渗等级p6是什么意思_混凝土p6是什么意思「建议收藏」展开全部40是混凝土的强度等62616964757a686964616fe58685e5aeb931333431356664级,P6是抗渗混凝土按抗渗压力。抗渗混凝土按抗渗压力不同分为P6、P8、P10、P12和大于P12共5个等级。抗渗混凝土通过提高混凝土的密实度,改善孔隙结构,从而减少渗透通道,提高抗渗性。混凝土按标准抗压强度(以边长为150mm的立方体为标准试件,在标准养护条件下养护28天,…

    2022年8月10日
    8

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号