博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
springboot -- 自定义(可预知和不可预知) Exception 异常的抛出和统一捕获处理
阅读量:3921 次
发布时间:2019-05-23

本文共 5771 字,大约阅读时间需要 19 分钟。

导言:

一般异常处理并返回到客户端是因为客户端需要知道错误信息

如果不是这样的话,处理程序的内部异常一般打印日志去标记或者捕获一下就可以了

打印日志:private static final Logger LOGGER = LoggerFactory.getLogger(PageService.class);

关于异常的执行:

若添加try catch语句则程序会处理异常,try内异常不再执行,处理后继续向下运行

若没有try catch语句 程序会在异常处跳出来,不再运行下面部分

个人理解是你主动 throw 一个异常出来, 如果不用try cath 捕获的话, 下面的代码是不会执行的;

如果你当场用try cath捕获了, 下面的代码会继续执行。


关于异常统一捕获处理

当你在Service层throw抛出了一个异常, 那么如果没有专门的异常捕获类, 异常就要交给Controller层去处理了,我们不希望Controller层处理异常, 所以要设置一个专门的异常捕获类

优点:
1、我们可以对异常信息进行详细描述, 使得返回客户端的信息有辨识度(不单纯发操作失败和错误代码)
2、捕获大部分异常, 减少try catch 代码冗余问题

大概流程思想:

在这里插入图片描述


关于可预知和不可预知异常

可预知:由程序员在代码有可能出错的地方手动抛出一个异常

不可预知:不可预知异常通常由SpringMVC或者第三方依赖等抛出的异常,程序员一般不可知


1、首先自定义一个异常:

package com.xuecheng.framework.exception;import com.xuecheng.framework.model.response.ResultCode;/** * @author Huang * @version 1.0 * @date 2020/3/27 10:49 */public class CustomException extends RuntimeException {
private ResultCode resultCode; public CustomException(){
} public CustomException(ResultCode resultCode){
//异常信息为错误代码+异常信息 super("错误代码:"+resultCode.code()+"错误信息:"+resultCode.message()); this.resultCode = resultCode; } public ResultCode getResultCode(){
return resultCode; }}

1、注意此处的自定义异常类是继承RuntimeException,而不是Exception。

如果继承Exception, 当你throw new Exception时, 程序编译时会要求你在方法处抛出该异常或者用try catch捕获该异常, 对代码有侵入性,而RuntimeException不会有上述要求
2、一定要写super("…");否则会报空指针异常
3、ResultCode resultCode 是异常的返回消息, 返回给客户端即可看到错误的详情信息

2、对抛出异常的语句进行包装(可选择不包装):

package com.xuecheng.framework.exception;import com.xuecheng.framework.model.response.ResultCode;/** * @author Huang * @version 1.0 * @date 2020/3/27 11:00 *///对抛出异常代码进行包装, 使其使用的更简洁(其实区别不大)public class ExceptionCast {    public static void cast(ResultCode resultCode){        throw new CustomException(resultCode);    }}

不包装的抛出异常

throw new CustomException(resultCode)

包装后的抛出异常

ExceptionCast.cast(resultCode);

3、此处抛出一个异常:

if(null!=byPageNameAndSiteIdAndPageWebPath){
ExceptionCast.cast(CmsCode.CMS_ADDPAGE_EXISTSNAME);}

注:CmsCode.CMS_ADDPAGE_EXISTSNAME是一个resultCode的实现枚举类对象

4、创建一个处理异常的类(可预知异常):

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;/** * 自定义异常统一捕获器 * @author Huang * @version 1.0 * @date 2020/3/27 11:04 */@ControllerAdvice //控制器增强public class ExceptionCatch {
private static final Logger logger = LoggerFactory.getLogger(ExceptionCatch.class); //捕获可预知自定义CustomException类异常的方法 @ResponseBody @ExceptionHandler(CustomException.class) public ResponseResult handlerCustomException(CustomException customException){
//记录日志 logger.error("捕获到一个可预知异常:" + customException.getMessage()); //获取该异常的代码 ResultCode resultCode = customException.getResultCode(); //返回结果响应体 return new ResponseResult(resultCode); }}

不可预知异常

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.boot.context.properties.bind.BindException;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;import org.springframework.web.bind.annotation.RestController;/** * 自定义不可预知异常统一捕获器 * @author Huang * @version 1.0 * @date 2020/3/27 11:04 */@ControllerAdvice //控制器增强public class ExceptionCatch {    private static final Logger logger = LoggerFactory.getLogger(ExceptionCatch.class);    //定义exceptionsMap, 存放异常类型和错误代码信息对应key-value    //ImmutableMap的特点的一旦创建不可改变,并且线程安全    private static ImmutableMap
, ResultCode> exceptionsMap; //定义exceptionsMap的builder对象,通过builder存放数据后再赋值给exceptionsMap,构建exceptionsMap protected static ImmutableMap.Builder
, ResultCode> builder = ImmutableMap.builder(); //静态方法体, 每次程序运行后,该类只会执行一次 //初始化builder中不可预知异常类的对应错误信息 static { builder.put(HttpMessageNotReadableException.class, CommonCode.INVALID_PARAM); //缺少实体参数 } //不可预知异常通常由SpringMVC或者第三方依赖等抛出的异常,程序员一般不可知 //捕获并设置返回信息 //捕获不可预知自定义Exception类异常的方法 @ResponseBody @ExceptionHandler(BindException.class) public ResponseResult handlerException(Exception exception){ //记录日志 logger.error("捕获到一个不可预知异常:" + exception.getMessage()); if(null==exceptionsMap){ exceptionsMap = builder.build(); //exceptionsMap构建成功 } ResultCode resultCode = exceptionsMap.get(exception.getClass()); //获取对应异常的对应错误信息 ResponseResult responseResult; //找到了对应的错误信息 if(null!=resultCode){ responseResult = new ResponseResult(resultCode); } else{ responseResult = new ResponseResult(CommonCode.SERVER_ERROR); } //返回结果响应体 return responseResult; }}

注:这里的 ImmutableMap 是一个泛型的Map,因为不可预知的异常有N多种,所以要用?泛型来装载这些异常类型(Throwable是所有Exception的父类)

0、 ImmutableMap的特点的一旦创建不可改变,并且线程安全
1、ImmutableMap ----- exceptionsMap:存放异常类型和错误代码信息对应key-value
2、builder对象:通过builder存放数据后再赋值给exceptionsMap,构建exceptionsMap
3、statIc方法块中的就是初始化builder了,Key是异常的类, Value是错误信息


关于部分注解

@ControllerAdvice (增强控制器)代表了全局处理,可以全局处理数据,全局处理异常等。这里运用于全局异常处理, 表示这个类是全局可以访问的。

@ExceptionHandler(UserNoExit.class)表示该方法只处理该异常类型
@ResponseBody表示以json格式返回消息体到客户端


如果抛出异常不处理的话就会显示错误页面(这个页面是自定义过的的):表示服务端出现错误

在这里插入图片描述


成功捕获异常:

在这里插入图片描述

第一行是日志错误信息
第二行是成功捕获异常信息

转载地址:http://ruern.baihongyu.com/

你可能感兴趣的文章
Nmcli 网络管理命令行工具
查看>>
Linux IP地址配置
查看>>
firewalld和iptables
查看>>
SELinux
查看>>
nmcli双网卡绑定
查看>>
nmcli 网卡链路绑定team
查看>>
Linux下profile和bashrc四种的区别
查看>>
Linux文件查看指令整理
查看>>
Linux的三个时间参数
查看>>
Linux 用户ID和组ID
查看>>
Linux /etc/passwd文件
查看>>
Linux 档案搜寻指令整理
查看>>
RAID和LVM
查看>>
网关和路由的区别
查看>>
rc.local文件
查看>>
service命令
查看>>
服务器修改主机名
查看>>
Linux的ip指令
查看>>
mount(挂载)详解
查看>>
Centos7安装pssh2.3版本
查看>>