适配层Adapter
@Api(tags = "邮箱配置")
@Slf4j
@RestController
@RequestMapping("mailConfig")
public class SysMailConfigController {
@Autowired
private SysMailConfigAppService sysMailConfigAppService;
@ApiOperation("删除邮箱信息")
@PostMapping(value = "delete.json")
public AjaxResult<Boolean> delete(@RequestParam("id") Integer id) {
UserInfo userInfo = UserUtils.getUserInfo();
sysMailConfigAppService.deleteById(id, userInfo);
return AjaxResult.success(Boolean.TRUE);
}
@ApiOperation("创建或更新邮箱")
@PostMapping("createOrUpdate.json")
public AjaxResult<Boolean> createOrUpdate(@RequestBody SysMailConfigDTO sysMailConfigDTO) {
UserInfo userInfo = UserUtils.getUserInfo();
sysMailConfigAppService.createOrUpdate(sysMailConfigDTO, userInfo);
return AjaxResult.success(Boolean.TRUE);
}
@ApiOperation("分页查询")
@PostMapping("listByPage.json")
public PageResult<List<SysMailConfigVO>> listByPage(@RequestBody PageParam<SysMailConfigDTO> pageParam) {
UserInfo userInfo = UserUtils.getUserInfo();
return sysMailConfigAppService.selectPage(pageParam, userInfo);
}
}
应用层Application
@Slf4j
@Service
public class SysMailConfigAppServiceImpl implements SysMailConfigAppService {
@Autowired
private SysMailConfigConverter sysMailConfigConverter;
@Autowired
private SysMailConfigDomainService sysMailConfigDomainService;
@Override
public PageResult<List<SysMailConfigVO>> selectPage(PageParam<SysMailConfigDTO> pageParam, UserInfo userInfo) {
// 开启分页查询
PageHelper.startPage(pageParam.getPage(), pageParam.getSize());
// DTO转Model
SysMailConfigModel sysMailConfigModel = sysMailConfigConverter.dtoToModel(pageParam.getData());
// 查询用户列表
List<SysMailConfigModel> sysMailConfigModelList = sysMailConfigDomainService.listByParam(sysMailConfigModel);
// Model转VO
List<SysMailConfigVO> sysMailConfigVOList = sysMailConfigModelList.stream().map(sysMailConfigConverter::modelToVO).collect(Collectors.toList());
// 封装为PageInfo对象
PageInfo<SysMailConfigVO> pageInfo = new PageInfo<>(sysMailConfigVOList);
// 封装返回结果
PageResult<List<SysMailConfigVO>> pageResult = new PageResult<>();
pageResult.setTotal(pageInfo.getTotal());
pageResult.setData(sysMailConfigVOList);
pageResult.setSize((pageInfo.getPageSize()));
return pageResult;
}
@Override
public void createOrUpdate(SysMailConfigDTO sysMailConfigDTO, UserInfo userInfo) {
// DTO转Model
SysMailConfigModel sysMailConfigModel = sysMailConfigConverter.dtoToModel(sysMailConfigDTO);
sysMailConfigDomainService.createOrUpdate(sysMailConfigModel);
}
@Override
public void deleteById(Integer id, UserInfo userInfo) {
sysMailConfigDomainService.deleteById(id);
}
}
领域层Domain
@Slf4j
@Service
public class SysMailConfigDomainServiceImpl implements SysMailConfigDomainService {
@Autowired
private SysMailConfigRepository sysMailConfigRepository;
@Override
public void createOrUpdate(SysMailConfigModel sysMailConfigModel) {
if (sysMailConfigModel.getId() == null) {
sysMailConfigModel.setStatus(SysMailConfigStatusEnum.COMMON.name());
sysMailConfigRepository.save(sysMailConfigModel);
} else {
sysMailConfigRepository.update(sysMailConfigModel);
}
}
@Override
public void deleteById(Integer id) {
ValidateUtil.notNull(id, "id is null");
SysMailConfigModel sysMailConfigModel = new SysMailConfigModel();
sysMailConfigModel.setId(id.longValue());
sysMailConfigModel.setStatus(SysMailConfigStatusEnum.DELETED.name());
sysMailConfigRepository.update(sysMailConfigModel);
}
@Override
public List<SysMailConfigModel> listByParam(SysMailConfigModel sysMailConfigModel) {
return sysMailConfigRepository.listByParam(sysMailConfigModel);
}
}
基础设施层Infrastructure
Repository仓储接口
@Slf4j
@Repository
public class SysMailConfigRepositoryImpl implements SysMailConfigRepository {
@Autowired
private SysMailConfigMapper sysMailConfigMapper;
@Autowired
private SysMailConfigConverter sysMailConfigConverter;
@Override
public void save(SysMailConfigModel sysMailConfigModel) {
SysMailConfigDO sysMailConfigDO = sysMailConfigConverter.modelToDO(sysMailConfigModel);
sysMailConfigMapper.insert(sysMailConfigDO);
}
@Override
public void update(SysMailConfigModel sysMailConfigModel) {
SysMailConfigDO sysMailConfigDO = sysMailConfigConverter.modelToDO(sysMailConfigModel);
sysMailConfigMapper.updateById(sysMailConfigDO);
}
@Override
public List<SysMailConfigModel> listByParam(SysMailConfigModel sysMailConfigModel) {
// 分页查询
List<SysMailConfigDO> sysMailConfigDOList = sysMailConfigMapper.listByParam(sysMailConfigModel);
if (CollectionUtils.isEmpty(sysMailConfigDOList)) {
return Collections.emptyList();
}
return sysMailConfigDOList.stream().map(sysMailConfigConverter::doToModel).collect(Collectors.toList());
}
}
- 控制器层的入参和出参使用DTO(
SysMailConfigDTO
)和VO(SysMailConfigVO
)对象进行替换,以避免直接暴露领域模型。 - 应用层的入参和出参也使用DTO和VO对象进行替换,同时在应用层中进行DTO和领域模型的转换。
- 适配层/表现层(控制器层)使用
AjaxResult
作为返回结果,以符合常见的RESTful API规范。 - 基础设施层中,持久化操作方法的返回类型改为
void
,以符合典型的Repository接口定义。
典型的Repository接口定义通常包括以下几个方面:
- 命名规范:Repository接口的命名通常以"领域实体+Repository"的方式命名,例如
SysMailConfigRepository
。 - 抽象方法:Repository接口定义了对领域实体进行持久化操作的抽象方法,如
save
、update
、delete
、findById
等。这些方法描述了对数据的常见操作。 - 参数类型:方法的参数类型通常是领域实体或与领域实体相关的对象,用于传递操作所需的数据。
- 返回类型:方法的返回类型通常是持久化操作的结果,如保存成功返回
void
、更新成功返回void
、查询操作返回领域实体或DTO等。 - 异常处理:Repository接口通常会声明可能发生的异常,如数据访问异常、数据一致性异常等。这样可以提供给调用者更丰富的异常处理信息。
总体来说,典型的Repository接口定义是为了抽象和定义对领域实体进行持久化操作的方法,以提供一种统一的数据访问接口。具体的定义会根据项目需求、技术栈和团队约定而有所不同。不同的编程语言和框架也会对Repository接口定义有一些差异。重要的是根据项目的实际情况和需求,设计合适的Repository接口,使其能够满足对数据的访问和操作需求。
通常情况下,DTO、VO、DO 和 Model 可以定义在领域层,但也可以根据实际需求和项目规模进行适当的调整。
- DTO(Data Transfer Object):DTO 是用于在不同层之间传输数据的对象。它可以包含多个领域对象或领域模型的部分数据,并且不应该包含业务逻辑。DTO 可以定义在领域层,用于在领域层和应用层之间进行数据交互。另外,如果应用层需要将数据传输到外部系统,也可以在应用层定义相应的 DTO。
- VO(View Object):VO 是用于在视图层展示数据的对象,通常与特定的视图结构相关。VO 可以定义在领域层,用于在领域层和表现层之间传输数据。在实际开发中,VO 也可以定义在表现层,以与特定的视图或前端框架紧密关联。
- DO(Data Object):DO 是用于表示和操作外部系统的数据对象,通常与数据库或其他持久化机制相关。DO 可以定义在基础设施层,用于与数据库或其他外部系统进行数据交互。
- Model:Model 是用于表示业务领域概念和规则的对象,通常包含业务逻辑和领域特定的行为。Model 通常定义在领域层,作为领域模型的一部分。
在许多项目中,DTO、VO、DO 和 Model 都可以定义在领域层,以保持领域层的内聚性和独立性。这种做法可以避免将领域内部的实现细节泄露到其他层。然而,在某些特定情况下,如大型系统或需要与外部系统密切集成的系统,可能需要在其他层中定义相应的对象。
需要根据具体项目的规模、需求和团队约定来决定在哪一层定义 DTO、VO、DO 和 Model,以保持清晰的分层结构和代码的可维护性。
在DDD(领域驱动设计)中,常见的分层架构包括以下几个层:
- 领域层(Domain Layer):领域层是DDD的核心,包含业务规则、领域模型和领域服务等。它负责表达业务概念,封装业务逻辑,并通过领域模型来解决业务问题。领域层独立于其他层,不依赖于具体的技术实现。
- 应用层(Application Layer):应用层负责协调领域层和用户界面或外部接口之间的交互。它处理用户请求,调用相应的领域服务或领域模型来实现业务操作。应用层负责处理事务、权限验证、编排用例等,并与领域层进行交互。
- 基础设施层(Infrastructure Layer):基础设施层提供支持应用程序运行的基础设施,包括数据库、文件系统、网络通信、消息队列等。它负责将领域层和外部技术进行适配和交互。基础设施层通常包含实现与具体技术相关的代码,如数据访问、外部服务调用等。
- 用户界面层(User Interface Layer):用户界面层是与用户交互的接口,可以是Web界面、移动应用程序、命令行界面等。它负责接收用户输入,并将其转发给应用层处理。用户界面层也负责显示领域对象的状态和结果给用户。
这些层之间的交互遵循依赖反转和依赖规则的原则,使得依赖关系保持向内的方向,实现高内聚、低耦合的设计。领域层作为核心层包含业务规则和领域逻辑,应用层负责协调和编排领域层,基础设施层提供支持和技术实现,用户界面层与用户进行交互。这种分层架构有助于实现可维护、可测试和可扩展的应用程序。
关于DDD分层架构的依赖关系描述的有些错误。在DDD中,通常倾向于使用依赖反转(Dependency Inversion)原则,以实现高内聚、低耦合的设计。以下是修正后的依赖关系描述:
- 领域层(Domain Layer):
- 领域层是整个架构的核心,应该不依赖于其他层。
- 领域层的职责是定义领域模型、领域服务和业务规则。
- 应用层(Application Layer):
- 应用层依赖于领域层,负责协调和编排领域对象的交互,但领域层不应依赖于应用层。
- 应用层的职责是处理用户请求、事务管理、查询处理等。
- 基础设施层(Infrastructure Layer):
- 基础设施层依赖于领域层和应用层,为它们提供支持和技术实现。
- 基础设施层的职责是与外部资源(如数据库、消息队列、外部服务等)进行交互,为应用层提供数据访问和其他基础设施功能。
- 用户界面层(User Interface Layer):
- 用户界面层依赖于应用层和基础设施层,负责与用户进行交互,但其他层不应依赖于用户界面层。
- 用户界面层的职责是处理用户输入和展示数据,将用户请求转发给应用层。
总结起来,领域层是核心层,应用层依赖于领域层,基础设施层依赖于领域层和应用层,用户界面层依赖于应用层和基础设施层。依赖关系应该遵循依赖反转原则,高层次的模块(如用户界面层)不应依赖于低层次的模块,而是通过接口进行交互。这样可以实现解耦、可测试和可扩展的架构设计。非常抱歉之前的描述会引起困惑,希望这次的修正能更准确地回答您的问题。
在DDD中,client层表示与外部客户端应用程序交互的层。这个层负责处理来自外部客户端的请求,并将其转发给应用层进行处理。client层可以包括各种类型的客户端,如Web界面、移动应用程序、命令行界面等。
依赖关系中,client层依赖于应用层和基础设施层,负责与外部客户端进行交互。它可以调用应用层的接口或服务来处理客户端请求,并将结果返回给客户端。
总结起来,完整的DDD分层架构包括以下层:
- 领域层(Domain Layer):核心业务逻辑和领域模型。
- 应用层(Application Layer):协调和编排领域层的交互。
- 基础设施层(Infrastructure Layer):提供支持和技术实现,如数据库、外部服务等。
- 用户界面层(User Interface Layer):处理用户输入和展示数据。
- Client层(Client Layer):与外部客户端应用程序进行交互。
这样的分层架构可以帮助实现高内聚、低耦合的设计,支持可维护、可测试和可扩展的应用程序。非常抱歉之前的遗漏,希望这次的回答更准确和完整。
在DDD的分层架构中,用户界面层依赖于Client层,用于与外部客户端应用程序进行交互。客户端可以是Web界面、移动应用程序、命令行界面等。
正确的依赖关系是:
- 用户界面层(User Interface Layer):
- 用户界面层依赖于Client层和应用层。
- 用户界面层负责处理用户输入和展示数据,与Client层进行交互,通过调用Client层的接口或服务与外部客户端进行通信。
- 用户界面层可能包含用户界面逻辑、视图模型(ViewModel)等。
- Client层(Client Layer):
- Client层是与外部客户端应用程序交互的层。
- Client层依赖于应用层和基础设施层,负责处理来自用户界面层的请求,并将其转发给应用层进行处理。
- Client层可以封装与外部客户端的通信细节,例如通过API调用或其他协议与外部客户端进行交互。
这样的依赖关系确保了用户界面层能够通过Client层与外部客户端进行交互,并将用户的请求转发给应用层进行处理。
感谢您的指正,再次对之前的错误回答表示歉意。如果还有其他问题,请随时提问。