当前位置:   article > 正文

自定义异常:可预知异常处理 与 不可预知异常处理_网站系统出现不可预知的错误

网站系统出现不可预知的错误

概念

在这里插入图片描述
对可预知异常和不可预知异常的处理方案:
1、自定义异常类型。
2、自定义错误代码及错误信息。
3、对于可预知的异常由程序员在代码中主动抛出,由SpringMVC统一捕获。
可预知异常是程序员在代码中手动抛出本系统定义的特定异常类型,由于是程序员抛出的异常,通常异常信息比较
齐全,程序员在抛出时会指定错误代码及错误信息,获取异常信息也比较方便。
4、对于不可预知的异常(运行时异常)由SpringMVC统一捕获Exception类型的异常。
不可预知异常通常是由于系统出现bug、或一些不要抗拒的错误(比如网络中断、服务器宕机等),异常类型为
RuntimeException类型(运行时异常)。
5、可预知的异常及不可预知的运行时异常最终会采用统一的信息格式(错误代码+错误信息)来表示,最终也会随请求响应给客户端。

处理步骤流程:
1、在controller、service、dao中程序员抛出自定义异常;springMVC框架抛出框架异常类型
2、统一由异常捕获类捕获异常,并进行处理
3、捕获到自定义异常则直接取出错误代码及错误信息,响应给用户。
4、捕获到非自定义异常类型首先从Map中找该异常类型是否对应具体的错误代码,如果有则取出错误代码和错误
信息并响应给用户,如果从Map中找不到异常类型所对应的错误代码则统一为99999错误代码并响应给用户。
5、将错误代码及错误信息以Json格式响应给用户。

应用背景

问题代码背景

//添加页面
public CmsPageResult add(CmsPage cmsPage){
	//校验页面是否存在,根据页面名称、站点Id、页面webpath查询
	CmsPage cmsPage1 = cmsPageRepository.findByPageNameAndSiteIdAndPageWebPath(cmsPage.getPageName(), cmsPage.getSiteId(), cmsPage.getPageWebPath());
    
    if(cmsPage1==null){
        cmsPage.setPageId(null);//添加页面主键由spring data 自动生成
        cmsPageRepository.save(cmsPage);
        //返回结果
        CmsPageResult cmsPageResult = new CmsPageResult(CommonCode.SUCCESS,cmsPage);
        return cmsPageResult;
    }
    return new CmsPageResult(CommonCode.FAIL,null);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

目标需求

1、上边的代码只要操作不成功仅向用户返回“错误代码:11111,失败信息:操作失败”,无法区别具体的错误信
息。
2、service方法在执行过程出现异常在哪捕获?在service中需要都加try/catch,如果在controller也需要添加
try/catch,代码冗余严重且不易维护。

解决方案

1、在Service方法中的编码顺序是先校验判断,有问题则抛出具体的异常信息,最后执行具体的业务操作,返回成
功信息。
2、在统一异常处理类中去捕获异常,无需controller捕获异常,向用户返回统一规范的响应信息。

可预知异常处理

在这里插入图片描述
自定义异常类:

package com.xuecheng.framework.exception;

import com.xuecheng.framework.model.response.ResultCode;

/**
 * 自定义异常类型
 */
public class CustomException extends RuntimeException {

    //异常错误代码
    ResultCode resultCode;

    public CustomException(ResultCode resultCode){
        this.resultCode = resultCode;
    }

    public ResultCode getResultCode(){
        return this.resultCode;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

异常抛出类:

package com.xuecheng.framework.exception;

import com.xuecheng.framework.model.response.ResultCode;

/**
 * 异常抛出类
 */
public class ExceptionCast {

    public static void cast(ResultCode resultCodeObj){
        throw new CustomException(resultCodeObj);
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

异常捕获类:

package com.xuecheng.framework.exception;

import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.model.response.ResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/*
统一异常捕获类
 */
@ControllerAdvice//控制器增强,用于捕获异常的控制器注解.
public class ExceptionCatch {

    //定义一个Logger日志记录变量,用于异常(由捕获类所产生的)日志.
    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionCatch.class);


    @ExceptionHandler(CustomException.class) // 括号内为异常抛出类,只要遇到CustomException这个类抛出的异常,就去捕获.
    @ResponseBody //用于将异常信息以Json字符串的形式响应到前端.
    public ResponseResult customExceptionOfResponseResult(CustomException customException){
       //记录日志
        LOGGER.error("catch exception:{}",customException.getMessage());

        ResultCode resultCode = customException.getResultCode();
        return new ResponseResult(resultCode);
    }


}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

要使用到异常的方法:

   // 新增页面
    public CmsPageResult add(CmsPage cmsPage){
        //1.检查页面是否存在 通过查询页面名称,站点id,页面webpath(虚拟路径)实现效验.
        CmsPage cmsPageResult = cmsPageRepositoryObj.findByPageNameAndSiteIdAndPageWebPath(cmsPage.getPageName(),
                cmsPage.getSiteId() ,cmsPage.getPageWebPath() );

            if (cmsPageResult != null){//如果不为空,则说明存在该页面,无法新增

                //抛出异常
                ExceptionCast.cast(CmsCode.CMS_ADDPAGE_EXISTSNAME);

            }

            //如果为空则说明数据库不存在该页面,则可以添加

        cmsPage.setPageId(null);//对页面主键传递空参数,由spring data自动生成
        cmsPageRepositoryObj.save(cmsPage); //将其形参出接收到的Controller层传来的数据保存到mongoDB数据库

        //返回结果到controller层
        return new CmsPageResult(CommonCode.SUCCESS,cmsPage);

    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

不可预知异常处理

异常捕获类:
注意:不可预知的异常捕获类并没有捕获你自定义的抛出异常类,而是直接捕获最高级别的’Exception.Class’异常.所以无论是需求上还是逻辑上都不需要应用到@自定义异常类型的类,以及@抛出异常的类.
因为只要某个业务层(如PageService这个类)触发(发生)了异常,那么就意味着触发了Exception.Class(因为所有异常都继承于它),进而就会触发本异常捕获类.

package com.xuecheng.framework.exception;

import com.google.common.collect.ImmutableMap;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.model.response.ResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/*
统一异常捕获类
 */
@ControllerAdvice//控制器增强,用于捕获异常的控制器注解.
public class ExceptionCatch {

    //定义一个Logger日志记录变量,用于异常(由捕获类所产生的)日志.
    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionCatch.class);



    //定义用于容纳异常类型的Map,存放异常类型所对应的错误代码.
    private static ImmutableMap<Class<? extends Throwable>,ResultCode> EXCEPTIONS;

    //定义上面map的builder对象,去构建上面的ImmutableMap
    protected static ImmutableMap.Builder<Class<? extends Throwable>,ResultCode> builderObj = ImmutableMap.builder();
    static {
        //为该对象异常类型(class)和对应的异常代码
        builderObj.put(HttpMessageNotReadableException.class, CommonCode.INVALID_PARAM);
    }


    @ExceptionHandler(Exception.class) // 括号内为异常抛出类,只要遇到CustomException这个类抛出的异常,就去捕获.
    @ResponseBody //用于将异常信息以Json字符串的形式响应到前端.
    public ResponseResult customExceptionOfResponseResult(Exception e){

       //记录日志
        LOGGER.error("catch exception:{}",e.getMessage());


        if (EXCEPTIONS == null){//如果尚未构建用于处理未知异常的ImmutableMap对象,则进行构建
           EXCEPTIONS = builderObj.build();//构建!
        }
        // 从EXCEPTIONS中寻找异常类型对应的错误代码,如果找到了将错误代码响应给用户,如果找不到就返回给用户9999
      final ResultCode resultCode = EXCEPTIONS.get(e.getClass());
        if (resultCode != null){//判断是否为未知异常.肺空(即map中获取不到这种类型的异常类)则为未知异常

            return new ResponseResult(resultCode);//如果为未知异常,则返回CommonCode的 10003,"非法参数!"

        }else {
            return new ResponseResult(resultCode);//如果不为空,则是不为未知异常,而为更大的不可预知的异常,则返回CommonCode的 99999,"抱歉,系统繁忙,请稍后重试!"
                                                    //当然,我们可以在map集合中添加此异常的异常class类,同时添加对应的异常代码和字符串信息.这个要根据具体的业务需求来编写了.

        }




    }


}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/86119
推荐阅读
相关标签
  

闽ICP备14008679号