欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 手游 > 【实战案例】SpringBoot项目中异常处理通用解决方案

【实战案例】SpringBoot项目中异常处理通用解决方案

2024/10/24 5:17:03 来源:https://blog.csdn.net/Gavin_915/article/details/142938228  浏览:    关键词:【实战案例】SpringBoot项目中异常处理通用解决方案

项目中经常会出现一些异常,比如在新增项目的时候必要的字段没有填写。在springboot项目中,遇到异常会往上抛出给调用方,DAO层遇到异常抛给Service层,Service层遇到异常抛给Controller层,Controller层遇到异常就抛给了SpringMVC框架。对于前端来说是无法感知的,并不知道具体发生了什么错误。如果使用try-catch的话代码又过于冗余,所以需要把异常处理的逻辑统一进行管理。
在这里插入图片描述
上图是设想的解决方案,通过SpringMVC提供的控制器增强类统一由一个类完成异常的捕获,背后是AOP机制。

实现过程:
枚举类CommonError用于定义常见的错误类型

package com.gavin.base.exception;/*** @author Gavin* @description 通用错误信息* @date 2024/10/15**/
public enum CommonError {UNKOWN_ERROR("执行过程异常,请重试。"),PARAMS_ERROR("非法参数"),OBJECT_NULL("对象为空"),QUERY_NULL("查询结果为空"),REQUEST_NULL("请求参数为空");private String errMessage;public String getErrMessage() {return errMessage;}private CommonError( String errMessage) {this.errMessage = errMessage;}
}

自定义异常类EffecttiveStudyException用来封装项目中特定异常信息

package com.gavin.base.exception;/*** @author Gavin* @description 自定义高效学习在线类项目异常类* @date 2024/10/15**/
public class EffectiveStudyException extends RuntimeException{private String errMessage;public EffectiveStudyException() {super();}public EffectiveStudyException(String errMessage) {super(errMessage);this.errMessage = errMessage;}public String getErrMessage() {return errMessage;}public static void cast(CommonError commonError){throw new EffectiveStudyException(commonError.getErrMessage());}public static void cast(String errMessage){throw new EffectiveStudyException(errMessage);}
}

错误响应类RestErrorResponse用于统一封装并返回给前端的错误信息

package com.gavin.base.exception;import java.io.Serializable;/*** @author Gavin* @description 和前端约定返回的异常信息* @date 2024/10/15**/
public class RestErrorResponse implements Serializable {private String errMessage;public RestErrorResponse(String errMessage){this.errMessage= errMessage;}public String getErrMessage() {return errMessage;}public void setErrMessage(String errMessage) {this.errMessage = errMessage;}
}

定义全局异常处理器GlobalExceptionHandler类,这个类可以认为就是AOP机制中的一个切面,在系统各种专门处理所有控制器方法抛出的异常。以下是两个比较重要的注解:
@ControllerAdvice:用来标识一个全局异常处理类,所有被@Controller注解的控制器中的异常都会被它捕获。
@ExceptionHandler:用于捕获特定类型的异常。在这里,EffectiveStudyException 和其他普通异常都分别有处理方法。

package com.gavin.base.exception;import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
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.ResponseStatus;/*** @author Gavin* @description 全局异常处理器* @date 2024/10/15**/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {@ResponseBody@ExceptionHandler(EffectiveStudyException.class)@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)public RestErrorResponse customException(EffectiveStudyException e) {log.error("【系统异常】{}",e.getErrMessage(),e);return new RestErrorResponse(e.getErrMessage());}@ResponseBody@ExceptionHandler(Exception.class)@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)public RestErrorResponse exception(Exception e) {log.error("【系统异常】{}",e.getMessage(),e);return new RestErrorResponse(CommonError.UNKOWN_ERROR.getErrMessage());}
}

通过上述全局异常处理器,任何抛出的EffectiveStudyException或未被预期的异常都会被这个类统一处理,并返回一个标准的错误信息。

上述自定义后,对于抛出异常的地方可以进行替换,例如

throw new RuntimeException("课程的价格不能为空且必须大于0");

可以替换为

throw new EffectiveStudyException("课程的价格不能为空且必须大于0");
或者
EffectiveStudyException.cast("课程的价格不能为空且必须大于0");

两种形式是等价的,但后者更为简洁。如果捕获了上述异常,前端返回的就是对应内容的json数据信息,如下:
在这里插入图片描述

当存在其他异常时,如controller中存在一个除数为0的情形,如果在Controller中没有进行显示的try-catch捕获,异常会被直接抛出,由SpringMVC框架捕获并向上传递,SpringMVC会将这个异常传递给全局异常处理器类(GlobalExceptionHandler类),由于不是EffectiveStudyException类型的错误,所以交由兜底Exception处理,返回了UNKOWN_ERROR对应的错误信息(这里对于常见错误可定义特定信息返回)。如下:
在这里插入图片描述

这里可能会存在疑问,为什么不直接返回e.getMessage()的具体信息而是笼统的执行过程异常请重试?考虑的因素有:异常具体信息中可能包含敏感的系统内部信息,如数据库查询语句,服务器路径及框架细节等信息,有风险。另外,复杂的信息用户体验不好,提示信息应该简洁友好。但实际中开发环境有时候是有必要放出具体异常信息的,生产环境不适合放具体异常信息。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com