Java中的异常处理与DDD领域驱动设计_领域模型异常的定义与边界

大敏吖_8436

大敏吖_8436

2026-02-21

821人浏览

原创

不该抛 RuntimeException,而应抛出自定义领域异常;异常需反映领域语义、置于领域层包下、禁止继承检查型异常;Repository 不声明 throws;Application Service 仅记录日志并控制回滚;Controller 映射为语义化 HTTP 响应。

java中的异常处理与ddd领域驱动设计_领域模型异常的定义与边界

领域模型里该不该 throw RuntimeException?

不该,但绝大多数人其实已经在用了——关键不是“能不能抛”,而是“抛什么、谁来捕获、怎么恢复”。DDD 要求异常必须反映领域语义,IllegalArgumentException 或 NullPointerException 这类 JVM 底层异常,对领域建模毫无意义。

实操建议:

  • 每个聚合根或实体内部只抛出自定义的领域异常,如 InsufficientBalanceException、InvalidOrderStatusTransitionException
  • 异常类必须放在领域层包下(如 com.example.banking.domain.exception),不能混在 infrastructure 或 application 层
  • 禁止继承 RuntimeException 以外的异常基类——检查型异常(Exception 子类)会污染领域对象的 API,强迫调用方处理技术细节
  • 构造函数里不做复杂校验;校验逻辑应封装在工厂方法或静态构造器中,失败时直接抛出领域异常

Repository 方法要不要声明 throws?

不要。Repository 是领域层契约,它的接口必须干净,不泄露数据访问细节。

常见错误现象:在 OrderRepository.findById() 上声明 throws SQLException 或 throws DataAccessException ——这等于把 JPA/Hibernate 的实现泄漏进了领域层。

实操建议:

  • Repository 接口方法一律不写 throws,所有底层异常都由 infrastructure 层拦截并转换为领域异常或静默处理(如返回 Optional.empty())
  • 当查询必然应存在却没查到时(例如根据 ID 加载已确认存在的聚合),抛 EntityNotFoundException(领域异常),而非让上层处理 EmptyResultDataAccessException
  • 批量操作失败需区分:部分失败用 PartialUpdateException 包含成功/失败 ID 列表;全部失败才按常规领域异常处理

Application Service 中怎么处理领域异常?

只做两件事:记录上下文、决定是否回滚。别在这里“修复”业务逻辑。

使用场景:用户提交转账请求,领域层抛出 InsufficientBalanceException,Application Service 不该尝试去充值或提示“请先存钱”,那是 UI 或 Domain Service 的事。

java-api-doc-generator
java-api-doc-generator

分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。

下载

实操建议:

  • 用 try-catch 捕获明确的领域异常类型,避免 catch RuntimeException 大而化之
  • 记录日志时必须带上聚合 ID、用例输入参数(脱敏后),例如:log.warn("Transfer failed for accountId={}, targetId={}: {}", accountId, targetId, e.getMessage())
  • Spring 环境下,在 service 方法上加 @Transactional,并在 @Transactional(rollbackFor = DomainException.class) 显式指定回滚条件
  • 不要在 catch 块里重新包装成 RuntimeException 向上传——上层(如 Controller)需要知道这是领域规则拒绝,不是系统故障

Controller 层收到领域异常后怎么响应?

映射成 HTTP 语义明确的状态码和错误体,而不是堆栈或泛化消息。

容易踩的坑:把 InsufficientBalanceException 统一转成 500 Internal Server Error,或者返回 “Operation failed” 这种前端无法解析的字符串。

实操建议:

  • 用 Spring 的 @ControllerAdvice + @ExceptionHandler 做全局映射,例如将 InsufficientBalanceException 映射为 409 Conflict,body 包含 code: "BALANCE_INSUFFICIENT" 和 message: "账户余额不足"
  • 错误 code 必须是机器可读的常量字符串(如 "ORDER_STATUS_INVALID"),不能拼接变量或带空格
  • 敏感字段(如账户号、金额)不出现在 error message 中;message 只用于前端展示,详情走单独的 debug_id 日志追踪
  • 避免在 Controller 里 new 异常再 throw——领域异常必须由领域对象自己抛出,否则边界就模糊了

最常被忽略的一点:领域异常的构造函数里别放业务计算逻辑。比如在 InsufficientBalanceException 的构造里调用 account.getAvailableBalance(),万一这个 getter 本身又抛异常,你就掉进双重异常陷阱了。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

驱动精灵
驱动精灵

驱动精灵基于驱动之家十余年的专业数据积累,驱动支持度高,已经为数亿用户解决了各种电脑驱动问题、系统故障,是目前有效的驱动软件,有需要的小伙伴快来保存下载体验吧!

下载

相关标签:

java

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

2025.08.06

2811

22

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

2026.01.26

517

25

hibernate和mybatis有哪些区别
hibernate和mybatis有哪些区别

hibernate和mybatis的区别:1、实现方式;2、性能;3、对象管理的对比;4、缓存机制。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

302

5

Hibernate框架介绍
Hibernate框架介绍

本专题整合了hibernate框架相关内容,阅读专题下面的文章了解更多详细内容。

2025.08.06

3053

15

Java Hibernate框架
Java Hibernate框架

本专题聚焦 Java 主流 ORM 框架 Hibernate 的学习与应用,系统讲解对象关系映射、实体类与表映射、HQL 查询、事务管理、缓存机制与性能优化。通过电商平台、企业管理系统和博客项目等实战案例,帮助学员掌握 Hibernate 在持久层开发中的核心技能。

2025.09.02

8180

14

Hibernate框架搭建
Hibernate框架搭建

本专题整合了Hibernate框架用法,阅读专题下面的文章了解更多详细内容。

2025.10.14

858

8

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

2023.10.24

6264

49

scripterror怎么解决
scripterror怎么解决

scripterror的解决办法有检查语法、文件路径、检查网络连接、浏览器兼容性、使用try-catch语句、使用开发者工具进行调试、更新浏览器和JavaScript库或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.18

1029

5

500error怎么解决
500error怎么解决

500error的解决办法有检查服务器日志、检查代码、检查服务器配置、更新软件版本、重新启动服务、调试代码和寻求帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.25

3260

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习