java service层应抛出语义明确的自定义业务异常,继承runtimeexception,避免模糊的runtimeexception;统一提供错误码、消息和上下文信息,并在内部消化技术异常后转化为对应业务异常。

Java 中自定义异常在 Service 层规范抛出,核心是让异常语义明确、层级清晰、可捕获可处理,避免直接 throw new RuntimeException() 这类模糊做法。
定义业务异常类,继承 RuntimeException
Service 层通常采用运行时异常(非检查异常),避免强制 try-catch 破坏业务逻辑连贯性。自定义异常应聚焦业务场景,比如:
- UserNotFoundException:查不到用户
- InsufficientBalanceException:余额不足
- OrderStatusConflictException:订单状态不支持当前操作
统一继承 RuntimeException,并提供含错误码、消息、原因的构造器:
public class InsufficientBalanceException extends RuntimeException {
private final String errorCode = "BALANCE_INSUFFICIENT";
private final Long userId;
public InsufficientBalanceException(Long userId) {
super("用户 " + userId + " 余额不足");
this.userId = userId;
}
public String getErrorCode() { return errorCode; }
public Long getUserId() { return userId; }
}
Service 方法只抛出有意义的业务异常
不要包装底层异常(如 SQLException、RedisConnectionException)后原样往上扔。应在 Service 内部消化技术异常,转为对应的业务异常或日志记录后降级处理。
- 查数据库没查到 → 抛 UserNotFoundException
- 扣款时余额校验失败 → 抛 InsufficientBalanceException
- 并发修改导致版本号不一致 → 抛 OptimisticLockException(可复用或自定义)
示例:
通过 Google 服务账户在代码中读取或写入用户的 Google 表格、文档、云盘或日历——无头、无需 OAuth 浏览器流程。适用于已获得服务账户凭证的情况。
public void deductBalance(Long userId, BigDecimal amount) {
User user = userMapper.selectById(userId);
if (user == null) {
throw new UserNotFoundException(userId);
}
if (user.getBalance().compareTo(amount)
<h3>统一异常处理器拦截并标准化响应</h3>
<p>在 Controller 层之上用 <strong>@ControllerAdvice + @ExceptionHandler</strong> 统一处理自定义异常,返回结构化 JSON(如 code/msg/data):</p>
<pre class="brush:java;toolbar:false;">@ExceptionHandler(InsufficientBalanceException.class)
public ResponseEntity<apiresponse> handleInsufficientBalance(
InsufficientBalanceException e) {
return ResponseEntity.badRequest().body(
ApiResponse.fail(e.getErrorCode(), e.getMessage())
);
}</apiresponse>
这样 Service 层专注表达“发生了什么”,不关心 HTTP 状态码或响应格式,职责更纯粹。
避免在 Service 中 catch 自己抛的异常
除非有明确的补偿逻辑(如扣款失败需回滚积分),否则不要在 Service 内部 try-catch 自定义业务异常再重新 throw —— 这会掩盖调用链路和语义。异常应自然向上冒泡,由更高层(如 ControllerAdvice 或调用方)决定如何响应或重试。
若需记录日志,建议用 AOP 或在统一异常处理器中记录,而非每个 service 方法都写 log.error。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










