一、引言
本篇内容是“异常统一处理”系列文章的重要组成部分,主要聚焦于对 BusinessException
的原理解析与异常处理机制,并给出测试案例。
- 关于 全局异常统一处理 的原理和完整实现逻辑,请参考文章:
《SpringBoot 全局异常统一处理(AOP):@RestControllerAdvice + @ExceptionHandler + @ResponseStatus》- 本文仅详细解析 BusinessException 的异常处理;其他类型异常的原理和处理方法,请参阅本文所在专栏内的其他文章。
二、业务异常原理
在Java企业级应用开发中,BusinessException
是一种常见的自定义异常类型,它通常继承自 java.lang.RuntimeException
类。这种异常专门用于表示业务逻辑层( BLL )出现的错误或不符合预期的情况,这些情况并不属于系统内部错误,但会导致当前业务流程无法正常完成。
由各种业务规则导致的异常情况,与系统级别的异常(如 IOException、NullPointerException等)不同,它们是业务逻辑上的错误
,例如用户输入非法(如登录时的用户名密码错误)、订单状态非法操作、库存不足无法完成购买等情况。
设计 BusinessException
的主要目的是为了统一处理业务相关的错误,并方便异常传播时携带特定的业务上下文信息,如错误码、错误消息等。通过抛出 BusinessException
,开发者可以清晰地区分并优雅地处理那些由应用程序业务规则违反导致的问题,而不是因编程错误或系统故障引起的异常。
在实际使用中,当业务执行过程中出现错误时(如用户输入非法、资源不足、权限不够等情况),可抛出此异常,并附带相应的错误码和详细错误信息,这样上层服务或者全局异常处理器
就能根据异常类型和错误码来采取相应的恢复措施,比如记录日志、向客户端返回友好的提示信息以及进行事务回滚等操作。
三、业务异常代码
BusinessException
package com.example.core.model;import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;/*** 业务异常*/
@Getter
@Schema(name = "业务异常", description = "业务异常")
public class BusinessException extends RuntimeException {@Schema(description = "用户提示", example = "操作成功!")private final String userMessage;/*** 错误码<br>* 调用成功时,为 null。<br>* 示例:10001*/@Schema(description = "错误码")private final String errorCode;/*** 错误信息<br>* 调用成功时,为 null。<br>* 示例:"验证码无效"*/@Schema(description = "错误信息")private final String errorMessage;public BusinessException(ErrorEnum errorEnum) {super(String.format("错误码:[%s],错误信息:[%s],用户提示:[%s]", errorEnum.name(), errorEnum.getMessage(), errorEnum.getMessage()));this.userMessage = errorEnum.getMessage();this.errorCode = errorEnum.name();this.errorMessage = errorEnum.getMessage();}public BusinessException(String userMessage, String errorCode, String errorMessage) {super(String.format("错误码:[%s],错误信息:[%s],用户提示:[%s]", errorCode, errorMessage, userMessage));this.userMessage = userMessage;this.errorCode = errorCode;this.errorMessage = errorMessage;}}
ErrorEnum
下文为错误枚举的代码,本代码仅为示例,具体的错误枚举类型,应该按照公司的开发标准制定。
package com.example.core.model;import lombok.AllArgsConstructor;
import lombok.Getter;/*** 错误枚举*/
@Getter
@AllArgsConstructor
public enum ErrorEnum {A0001("用户端错误 "), // 一级宏观错误码// ------------------------------------------------------------------------------- //A0100("用户注册错误"), // 二级宏观错误码A0101("用户未同意隐私协议"),A0102("注册国家或地区受限"),A0110("用户名校验失败"),A0111("用户名已存在"),A0112("用户名包含敏感词"),A0113("用户名包含特殊字符"),// ------------------------------------------------------------------------------- //A0200("用户登录异常"), // 二级宏观错误码A0201("用户账户不存在"),A0202("用户账户被冻结"),A0203("用户账户已作废"),A0210("用户密码错误"),A0211("用户输入密码错误次数超限"),// ------------------------------------------------------------------------------- //A0400("用户请求参数错误"), // 二级宏观错误码A0420("请求参数值超出允许的范围"),A0421("参数格式不匹配"),A0422("地址不在服务范"),A0423("时间不在服务范围"),A0424("金额超出限制"),A0425("数量超出限制"),A0426("请求批量处理总个数超出限制"),A0427("请求 JSON 解析失败");private final String message;}
四、异常处理代码
在Spring Boot应用中,我们可以通过使用@ExceptionHandler
注解来捕获并处理BusinessException
异常。
4.1 异常处理示意图
4.2 异常处理核心代码
package com.example.core.advice;import com.example.core.model.BusinessException;
import com.example.core.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.HandlerMethod;/*** 全局异常处理器*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {/*** 业务异常处理*/@ExceptionHandler@ResponseStatus(HttpStatus.BAD_REQUEST)public Result<Void> handle(BusinessException e, HandlerMethod handlerMethod) {// BusinessException(自定义业务异常)的处理逻辑,比如:记录日志等逻辑。return Result.fail(e.getUserMessage(), e.getErrorCode(), e.getErrorMessage());}}
上述代码中,当出现BusinessException
异常时,系统将返回一个状态码为400(Bad Request)的结果,并附带具体的错误信息。
五、测试案例
5.1 测试代码
@GetMapping("business_exception")@Operation(summary = "业务异常", description = "测试 “业务异常”:直接将业务异常抛出,由 “异常统一处理” 模块来进行处理,将错误信息返回给前端。")public void throwBusinessException() {throw new BusinessException(ErrorEnum.A0210);}
5.2 未处理异常时的报错
请求响应
控制台的错误日志