如何使用Spring Modulith组织项目包结构?


我希望使用 Spring Modulith 并根据业务领域的模块对代码进行分组。

我当前的项目结构如下所示:

  • advice
  • config
  • controller
  • domain
  • dto
  • exception
  • repo
  • service

我找到了一些示例。它们都有不同的结构,没有一个完全遵循指南。

因此,我想知道推荐的方法是什么,比方说,我将这三个模块命名为:用户、投票和帖子。

正确/推荐的结构是这样的吗?

├ user -- package
│ ├ UserController.java
│ ├ UserService.java
│ ├ UserCreateDto.java
│ └ UserReadDto.java
└ user.internal -- package
  ├ UserRepository.java
  ├ User.java
  └ UserNotFoundException.java

回答:
请注意,在仅存在单个模块的情况下讨论模块结构是没有意义的。Spring Modulith 主要帮助将代码组织成多个功能模块。您在这些模块中使用什么样的技术组织实际上有点超出了范围,因为它本质上是模块的实现细节,因此不会影响整体安排的可维护性。

两种选择:

单包方法
只需一个user包中即可。需要被其他模块访问的类型需要声明public(+)。其他一切都保持包私有 ( o)。

└ user
  ├ + User.java
  ├ o UserController.java
  ├ o UserCreateDto.java
  ├ + UserNotFoundException.java // Assuming this is thrown from UserService
  ├ o UserRepository.java
  ├ + UserService.java
  └ o UserReadDto.java

选择技术组织方案进一步构建模块内容


├ user
│ ├ + User.java
│ ├ o UserRepository.java
│ ├ + UserService.java
│ └ + UserNotFoundException.java
└ user.web
  ├ o UserController.java
  ├ o UserCreateDto.java
  └ o UserReadDto.java

从 Spring Modulith 的角度来看,这种安排没有任何区别,因为web其他模块仍然无法访问其中的所有内容。
将类型移动到单独的包中可能会更容易进一步约束其中的代码。例如,只有指定包中的代码web才可以访问 Spring MVC、Servlet API 等。

在洋葱架构中,web属于基础设施环,服务实现到应用程序一环。其他一切都属于域。

将其映射到六边形架构需要您引入一个接口,以便UserService您可以设置端口(接口)和应用程序(实现)安排。

包中的代码web就构成了一个适配器。也就是说,这只是不同的行话,而不是根本不同的方法。

请注意,包不一定是将角色分配给某些类型的最佳方法。它们的主要目的是提供封装方法,简单方法可以最大限度地利用这种方法,因为我们只能依靠编译器来强制可见性。

除了包之外,您可能还想查看jMolecules。这为您提供了注释和接口形式的词汇表(洋葱、六角架构),以便您可以将这些架构角色分配给类型,并通过相应的 ArchUnit 规则获得依赖项验证